Merge branch 'new_api'

This commit is contained in:
irungentoo 2015-03-23 16:57:34 -04:00
commit 3fab804098
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
39 changed files with 5657 additions and 4513 deletions

View File

@ -29,13 +29,13 @@ unsigned char known_key2[crypto_box_BEFORENMBYTES] = {0x7a, 0xfa, 0x95, 0x45, 0x
// same as above, except standard opslimit instead of extra ops limit for test_known_kdf, and hash pw before kdf for compat
/* cause I'm shameless */
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
tox_add_friend_norequest(m, public_key);
tox_friend_add_norequest(m, public_key, 0);
}
}
@ -55,29 +55,29 @@ END_TEST
START_TEST(test_save_friend)
{
Tox *tox1 = tox_new(0);
Tox *tox2 = tox_new(0);
TOX_ERR_NEW err = TOX_ERR_NEW_OK;
Tox *tox1 = tox_new(0, 0, 0, 0);
Tox *tox2 = tox_new(0, 0, 0, 0);
ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances");
uint32_t to_compare = 974536;
tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox2, address);
int test = tox_add_friend(tox1, address, (uint8_t *)"Gentoo", 7);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address);
int test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0);
ck_assert_msg(test == 0, "Failed to add friend error code: %i", test);
uint32_t size = tox_encrypted_size(tox1);
uint8_t data[size];
test = tox_encrypted_save(tox1, data, "correcthorsebatterystaple", 25);
ck_assert_msg(test == 0, "failed to encrypted save");
ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing");
//ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing");
Tox *tox3 = tox_new(0);
test = tox_encrypted_load(tox3, data, size, "correcthorsebatterystaple", 25);
ck_assert_msg(test == 0, "failed to encrypted load");
uint8_t address2[TOX_CLIENT_ID_SIZE];
test = tox_get_client_id(tox3, 0, address2);
ck_assert_msg(test == 0, "no friends!");
ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match!");
Tox *tox3 = tox_encrypted_new(0, data, size, "correcthorsebatterystaple", 25, &err);
ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new");
uint8_t address2[TOX_PUBLIC_KEY_SIZE];
test = tox_friend_get_public_key(tox3, 0, address2, 0);
ck_assert_msg(test == 1, "no friends!");
ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match!");
size = tox_encrypted_size(tox3);
uint8_t data2[size];
@ -86,20 +86,19 @@ START_TEST(test_save_friend)
memcpy(key + 32, known_key2, crypto_box_BEFORENMBYTES);
test = tox_encrypted_key_save(tox3, data2, key);
ck_assert_msg(test == 0, "failed to encrypted save the second");
ck_assert_msg(tox_is_save_encrypted(data2) == 1, "magic number the second missing");
//ck_assert_msg(tox_is_save_encrypted(data2) == 1, "magic number the second missing");
// first test tox_encrypted_key_load
Tox *tox4 = tox_new(0);
test = tox_encrypted_key_load(tox4, data2, size, key);
ck_assert_msg(test == 0, "failed to encrypted load the second");
uint8_t address4[TOX_CLIENT_ID_SIZE];
test = tox_get_client_id(tox4, 0, address4);
ck_assert_msg(test == 0, "no friends! the second");
ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the second");
// first test tox_encrypted_key_new
Tox *tox4 = tox_encrypted_key_new(0, data2, size, key, &err);
ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new the second");
uint8_t address4[TOX_PUBLIC_KEY_SIZE];
test = tox_friend_get_public_key(tox4, 0, address4, 0);
ck_assert_msg(test == 1, "no friends! the second");
ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the second");
// now test compaitibilty with tox_encrypted_load, first manually...
// now test compaitibilty with tox_encrypted_new, first manually...
uint8_t out1[size], out2[size];
printf("Trying to decrypt from pw:\n");
//printf("Trying to decrypt from pw:\n");
uint32_t sz1 = tox_pass_decrypt(data2, size, pw, pwlen, out1);
uint32_t sz2 = tox_pass_key_decrypt(data2, size, key, out2);
ck_assert_msg(sz1 == sz2, "differing output sizes");
@ -107,13 +106,12 @@ 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
// to remove the manual check now that it's there)
Tox *tox5 = tox_new(0);
test = tox_encrypted_load(tox5, data2, size, pw, pwlen);
ck_assert_msg(test == 0, "failed to encrypted load the third");
uint8_t address5[TOX_CLIENT_ID_SIZE];
test = tox_get_client_id(tox4, 0, address5);
ck_assert_msg(test == 0, "no friends! the third");
ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the third");
Tox *tox5 = tox_encrypted_new(0, data2, size, pw, pwlen, &err);
ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new the third");
uint8_t address5[TOX_PUBLIC_KEY_SIZE];
test = tox_friend_get_public_key(tox4, 0, address5, 0);
ck_assert_msg(test == 1, "no friends! the third");
ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the third");
tox_kill(tox1);
tox_kill(tox2);

View File

@ -50,10 +50,10 @@ START_TEST(test_m_sendmesage)
int bad_len = MAX_CRYPTO_PACKET_SIZE;
ck_assert(m_sendmessage(m, -1, (uint8_t *)message, good_len) == 0);
ck_assert(m_sendmessage(m, REALLY_BIG_NUMBER, (uint8_t *)message, good_len) == 0);
ck_assert(m_sendmessage(m, 17, (uint8_t *)message, good_len) == 0);
ck_assert(m_sendmessage(m, friend_id_num, (uint8_t *)message, bad_len) == 0);
ck_assert(m_send_message_generic(m, -1, MESSAGE_NORMAL, (uint8_t *)message, good_len, 0) == -1);
ck_assert(m_send_message_generic(m, REALLY_BIG_NUMBER, MESSAGE_NORMAL, (uint8_t *)message, good_len, 0) == -1);
ck_assert(m_send_message_generic(m, 17, MESSAGE_NORMAL, (uint8_t *)message, good_len, 0) == -1);
ck_assert(m_send_message_generic(m, friend_id_num, MESSAGE_NORMAL, (uint8_t *)message, bad_len, 0) == -2);
}
END_TEST
@ -68,10 +68,10 @@ START_TEST(test_m_get_userstatus_size)
rc = m_get_statusmessage_size(m, friend_id_num);
/* this WILL error if the original m_addfriend_norequest() failed */
ck_assert_msg((rc > 0 && rc <= MAX_STATUSMESSAGE_LENGTH),
"m_get_statusmessage_size is returning out of range values!\n"
ck_assert_msg((rc >= 0 && rc <= MAX_STATUSMESSAGE_LENGTH),
"m_get_statusmessage_size is returning out of range values! (%i)\n"
"(this can be caused by the error of m_addfriend_norequest"
" in the beginning of the suite)\n");
" in the beginning of the suite)\n", rc);
}
END_TEST
@ -337,7 +337,7 @@ int main(int argc, char *argv[])
/* IPv6 status from global define */
Messenger_Options options = {0};
options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
m = new_messenger(&options);
m = new_messenger(&options, 0);
/* setup a default friend and friendnum */
if (m_addfriend_norequest(m, (uint8_t *)friend_id) < 0)

View File

@ -21,22 +21,28 @@
#define c_sleep(x) usleep(1000*x)
#endif
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
tox_add_friend_norequest(m, public_key);
tox_friend_add_norequest(m, public_key, 0);
}
}
uint32_t messages_received;
void print_message(Tox *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (type != TOX_MESSAGE_TYPE_NORMAL) {
ck_abort_msg("Bad type");
}
uint8_t cmp_msg[TOX_MAX_MESSAGE_LENGTH];
memset(cmp_msg, 'G', sizeof(cmp_msg));
@ -46,7 +52,7 @@ void print_message(Tox *m, int friendnumber, const uint8_t *string, uint16_t len
uint32_t name_changes;
void print_nickchange(Tox *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
@ -55,9 +61,19 @@ void print_nickchange(Tox *m, int friendnumber, const uint8_t *string, uint16_t
++name_changes;
}
uint32_t status_m_changes;
void print_status_m_change(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, void *user_data)
{
if (*((uint32_t *)user_data) != 974536)
return;
if (length == sizeof("Installing Gentoo") && memcmp(message, "Installing Gentoo", sizeof("Installing Gentoo")) == 0)
++status_m_changes;
}
uint32_t typing_changes;
void print_typingchange(Tox *m, int friendnumber, uint8_t typing, void *userdata)
void print_typingchange(Tox *m, uint32_t friendnumber, bool typing, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
@ -70,12 +86,12 @@ void print_typingchange(Tox *m, int friendnumber, uint8_t typing, void *userdata
uint32_t custom_packet;
int handle_custom_packet(Tox *m, int32_t friend_num, const uint8_t *data, uint32_t len, void *object)
void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size_t len, void *object)
{
uint8_t number = *((uint32_t *)object);
if (len != TOX_MAX_CUSTOM_PACKET_SIZE)
return -1;
return;
uint8_t f_data[len];
memset(f_data, number, len);
@ -83,54 +99,168 @@ int handle_custom_packet(Tox *m, int32_t friend_num, const uint8_t *data, uint32
if (memcmp(f_data, data, len) == 0) {
++custom_packet;
} else {
printf("Custom packet fail. %u\n", number );
ck_abort_msg("Custom packet fail. %u", number);
}
return 0;
}
uint8_t filenum;
uint32_t file_accepted;
uint64_t file_size;
void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename,
uint16_t filename_length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (filename_length == sizeof("Gentoo.exe") && memcmp(filename, "Gentoo.exe", sizeof("Gentoo.exe")) == 0)
++file_accepted;
file_size = filesize;
tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_ACCEPT, NULL, 0);
}
uint32_t file_sent;
uint32_t sendf_ok;
void file_print_control(Tox *m, int friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type,
const uint8_t *data, uint16_t length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED)
tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_FINISHED, NULL, 0);
if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED)
file_sent = 1;
if (receive_send == 1 && control_type == TOX_FILECONTROL_ACCEPT)
sendf_ok = 1;
}
uint64_t size_recv;
uint8_t num;
void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata)
uint64_t sending_pos;
uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
uint8_t filenum;
uint32_t file_accepted;
uint64_t file_size;
void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize,
const uint8_t *filename, size_t filename_length, void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
if (kind != TOX_FILE_KIND_DATA) {
ck_abort_msg("Bad kind");
return;
}
if (!(filename_length == sizeof("Gentoo.exe") && memcmp(filename, "Gentoo.exe", sizeof("Gentoo.exe")) == 0)) {
ck_abort_msg("Bad filename");
return;
}
uint8_t file_id[TOX_FILE_ID_LENGTH];
if (!tox_file_get_file_id(tox, friend_number, file_number, file_id, 0)) {
ck_abort_msg("tox_file_get_file_id error");
}
if (memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) != 0) {
ck_abort_msg("bad file_id");
}
uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
if (memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) == 0) {
ck_abort_msg("empty file_id");
}
file_size = filesize;
if (filesize) {
sending_pos = size_recv = 1337;
TOX_ERR_FILE_SEEK err_s;
if (!tox_file_seek(tox, friend_number, file_number, 1337, &err_s)) {
ck_abort_msg("tox_file_seek error");
}
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
} else {
sending_pos = size_recv = 0;
}
TOX_ERR_FILE_CONTROL error;
if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) {
++file_accepted;
} else {
ck_abort_msg("tox_file_control failed. %i", error);
}
TOX_ERR_FILE_SEEK err_s;
if (tox_file_seek(tox, friend_number, file_number, 1234, &err_s)) {
ck_abort_msg("tox_file_seek no error");
}
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
}
uint32_t sendf_ok;
void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
void *userdata)
{
if (*((uint32_t *)userdata) != 974536)
return;
/* First send file num is 0.*/
if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME)
sendf_ok = 1;
}
uint64_t max_sending;
_Bool m_send_reached;
uint8_t sending_num;
_Bool file_sending_done;
void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length,
void *user_data)
{
if (*((uint32_t *)user_data) != 974536)
return;
if (!sendf_ok) {
ck_abort_msg("Didn't get resume control");
}
if (sending_pos != position) {
ck_abort_msg("Bad position %llu", position);
return;
}
if (length == 0) {
if (file_sending_done) {
ck_abort_msg("File sending already done.");
}
file_sending_done = 1;
return;
}
if (position + length > max_sending) {
if (m_send_reached) {
ck_abort_msg("Requested done file tranfer.");
}
length = max_sending - position;
m_send_reached = 1;
}
TOX_ERR_FILE_SEND_CHUNK error;
uint8_t f_data[length];
memset(f_data, sending_num, length);
if (tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error)) {
++sending_num;
sending_pos += length;
} else {
ck_abort_msg("Could not send chunk %i", error);
}
if (error != TOX_ERR_FILE_SEND_CHUNK_OK) {
ck_abort_msg("Wrong error code");
}
}
uint8_t num;
_Bool file_recv;
void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
size_t length, void *user_data)
{
if (*((uint32_t *)user_data) != 974536)
return;
if (size_recv != position) {
ck_abort_msg("Bad position");
return;
}
if (length == 0) {
file_recv = 1;
return;
}
uint8_t f_data[length];
memset(f_data, num, length);
++num;
@ -138,33 +268,59 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *dat
if (memcmp(f_data, data, length) == 0) {
size_recv += length;
} else {
printf("FILE_CORRUPTED\n");
ck_abort_msg("FILE_CORRUPTED");
}
}
unsigned int connected_t1;
void tox_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *user_data)
{
if (*((uint32_t *)user_data) != 974536)
return;
if (connected_t1 && !connection_status)
ck_abort_msg("Tox went offline");
connected_t1 = connection_status;
}
START_TEST(test_one)
{
Tox *tox1 = tox_new(0);
Tox *tox2 = tox_new(0);
Tox *tox1 = tox_new(0, 0, 0, 0);
Tox *tox2 = tox_new(0, 0, 0, 0);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox1, address);
ck_assert_msg(tox_add_friend(tox1, address, (uint8_t *)"m", 1) == TOX_FAERR_OWNKEY, "Adding own address worked.");
{
TOX_ERR_GET_PORT error;
ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
}
tox_get_address(tox2, address);
uint8_t message[TOX_MAX_FRIENDREQUEST_LENGTH + 1];
ck_assert_msg(tox_add_friend(tox1, address, NULL, 0) == TOX_FAERR_NOMESSAGE, "Sending request with no message worked.");
ck_assert_msg(tox_add_friend(tox1, address, message, sizeof(message)) == TOX_FAERR_TOOLONG,
"TOX_MAX_FRIENDREQUEST_LENGTH is too big.");
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox1, address);
TOX_ERR_FRIEND_ADD error;
uint32_t ret = tox_friend_add(tox1, address, (uint8_t *)"m", 1, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_OWN_KEY, "Adding own address worked.");
tox_self_get_address(tox2, address);
uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH + 1];
ret = tox_friend_add(tox1, address, NULL, 0, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NULL, "Sending request with no message worked.");
ret = tox_friend_add(tox1, address, message, 0, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NO_MESSAGE, "Sending request with no message worked.");
ret = tox_friend_add(tox1, address, message, sizeof(message), &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_TOO_LONG,
"TOX_MAX_FRIEND_REQUEST_LENGTH is too big.");
address[0]++;
ck_assert_msg(tox_add_friend(tox1, address, (uint8_t *)"m", 1) == TOX_FAERR_BADCHECKSUM,
ret = tox_friend_add(tox1, address, (uint8_t *)"m", 1, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM,
"Adding address with bad checksum worked.");
tox_get_address(tox2, address);
ck_assert_msg(tox_add_friend(tox1, address, message, TOX_MAX_FRIENDREQUEST_LENGTH) == 0, "Failed to add friend.");
ck_assert_msg(tox_add_friend(tox1, address, message, TOX_MAX_FRIENDREQUEST_LENGTH) == TOX_FAERR_ALREADYSENT,
"Adding friend twice worked.");
tox_self_get_address(tox2, address);
ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
ck_assert_msg(ret == 0 && error == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend.");
ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_ALREADY_SENT, "Adding friend twice worked.");
uint8_t name[TOX_MAX_NAME_LENGTH];
int i;
@ -173,22 +329,23 @@ START_TEST(test_one)
name[i] = rand();
}
tox_set_name(tox1, name, sizeof(name));
ck_assert_msg(tox_get_self_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH");
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");
size_t save_size = tox_size(tox1);
size_t save_size = tox_get_savedata_size(tox1);
uint8_t data[save_size];
tox_save(tox1, data);
tox_get_savedata(tox1, data);
tox_kill(tox2);
tox2 = tox_new(0);
ck_assert_msg(tox_load(tox2, data, save_size) == 0, "Load failed");
TOX_ERR_NEW err_n;
size_t length = tox_get_self_name_size(tox2);
ck_assert_msg(tox_get_self_name_size(tox2) == sizeof name, "Wrong name size.");
tox2 = tox_new(0, data, save_size, &err_n);
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.");
uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 };
ck_assert_msg(tox_get_self_name(tox2, new_name) == TOX_MAX_NAME_LENGTH, "Wrong name length");
tox_self_get_name(tox2, new_name);
ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
tox_kill(tox1);
@ -199,51 +356,83 @@ END_TEST
START_TEST(test_few_clients)
{
long long unsigned int con_time, cur_time = time(NULL);
Tox *tox1 = tox_new(0);
Tox *tox2 = tox_new(0);
Tox *tox3 = tox_new(0);
TOX_ERR_NEW t_n_error;
Tox *tox1 = tox_new(0, 0, 0, &t_n_error);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox2 = tox_new(0, 0, 0, &t_n_error);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox3 = tox_new(0, 0, 0, &t_n_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");
{
TOX_ERR_GET_PORT error;
ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
}
{
TOX_ERR_GET_PORT error;
ck_assert_msg(tox_self_get_udp_port(tox2, &error) == 33446, "Second Tox instance did not bind to udp port 33446.\n");
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
}
{
TOX_ERR_GET_PORT error;
ck_assert_msg(tox_self_get_udp_port(tox3, &error) == 33447, "Third Tox instance did not bind to udp port 33447.\n");
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
}
uint32_t to_compare = 974536;
connected_t1 = 0;
tox_callback_self_connection_status(tox1, tox_connection_status, &to_compare);
tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox2, address);
int test = tox_add_friend(tox3, address, (uint8_t *)"Gentoo", 7);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address);
uint32_t test = tox_friend_add(tox3, address, (uint8_t *)"Gentoo", 7, 0);
ck_assert_msg(test == 0, "Failed to add friend error code: %i", test);
uint8_t off = 1;
while (1) {
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) {
if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
&& tox_self_get_connection_status(tox3)) {
if (off) {
printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
con_time = time(NULL);
off = 0;
}
if (tox_get_friend_connection_status(tox2, 0) == 1 && tox_get_friend_connection_status(tox3, 0) == 1)
if (tox_friend_get_connection_status(tox2, 0, 0) == TOX_CONNECTION_UDP
&& tox_friend_get_connection_status(tox3, 0, 0) == TOX_CONNECTION_UDP)
break;
}
c_sleep(50);
}
ck_assert_msg(connected_t1, "Tox1 isn't connected. %u", connected_t1);
printf("tox clients connected took %llu seconds\n", time(NULL) - con_time);
to_compare = 974536;
tox_callback_friend_message(tox3, print_message, &to_compare);
uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1];
memset(msgs, 'G', sizeof(msgs));
ck_assert_msg(tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH + 1) == 0,
"TOX_MAX_MESSAGE_LENGTH is too small\n");
ck_assert_msg(tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH) != 0, "TOX_MAX_MESSAGE_LENGTH is too big\n");
TOX_ERR_FRIEND_SEND_MESSAGE errm;
tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm);
ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG, "TOX_MAX_MESSAGE_LENGTH is too small\n");
tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH, &errm);
ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_OK, "TOX_MAX_MESSAGE_LENGTH is too big\n");
while (1) {
messages_received = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (messages_received)
break;
@ -253,14 +442,16 @@ START_TEST(test_few_clients)
printf("tox clients messaging succeeded\n");
tox_callback_name_change(tox3, print_nickchange, &to_compare);
tox_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"));
tox_callback_friend_name(tox3, print_nickchange, &to_compare);
TOX_ERR_SET_INFO err_n;
bool succ = tox_self_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"), &err_n);
ck_assert_msg(succ && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %u\n", err_n);
while (1) {
name_changes = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (name_changes)
break;
@ -268,18 +459,42 @@ START_TEST(test_few_clients)
c_sleep(50);
}
ck_assert_msg(tox_friend_get_name_size(tox3, 0, 0) == sizeof("Gentoo"), "Name length not correct");
uint8_t temp_name[sizeof("Gentoo")];
tox_get_name(tox3, 0, temp_name);
tox_friend_get_name(tox3, 0, temp_name, 0);
ck_assert_msg(memcmp(temp_name, "Gentoo", sizeof("Gentoo")) == 0, "Name not correct");
tox_callback_typing_change(tox2, &print_typingchange, &to_compare);
tox_set_user_is_typing(tox3, 0, 1);
tox_callback_friend_status_message(tox3, print_status_m_change, &to_compare);
succ = tox_self_set_status_message(tox2, (uint8_t *)"Installing Gentoo", sizeof("Installing Gentoo"), &err_n);
ck_assert_msg(succ && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %u\n", err_n);
while (1) {
status_m_changes = 0;
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (status_m_changes)
break;
c_sleep(50);
}
ck_assert_msg(tox_friend_get_status_message_size(tox3, 0, 0) == sizeof("Installing Gentoo"),
"status message length not correct");
uint8_t temp_status_m[sizeof("Installing Gentoo")];
tox_friend_get_status_message(tox3, 0, temp_status_m, 0);
ck_assert_msg(memcmp(temp_status_m, "Installing Gentoo", sizeof("Installing Gentoo")) == 0,
"status message not correct");
tox_callback_friend_typing(tox2, &print_typingchange, &to_compare);
tox_self_set_typing(tox3, 0, 1, 0);
while (1) {
typing_changes = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (typing_changes == 2)
@ -290,14 +505,14 @@ START_TEST(test_few_clients)
c_sleep(50);
}
ck_assert_msg(tox_get_is_typing(tox2, 0) == 1, "Typing fail");
tox_set_user_is_typing(tox3, 0, 0);
ck_assert_msg(tox_friend_get_typing(tox2, 0, 0) == 1, "Typing fail");
tox_self_set_typing(tox3, 0, 0, 0);
while (1) {
typing_changes = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (typing_changes == 1)
break;
@ -307,23 +522,24 @@ START_TEST(test_few_clients)
c_sleep(50);
}
ck_assert_msg(tox_get_is_typing(tox2, 0) == 0, "Typing fail");
TOX_ERR_FRIEND_QUERY err_t;
ck_assert_msg(tox_friend_get_typing(tox2, 0, &err_t) == 0, "Typing fail");
ck_assert_msg(err_t == TOX_ERR_FRIEND_QUERY_OK, "Typing fail");
uint32_t packet_number = 160;
int ret = tox_lossless_packet_registerhandler(tox3, 0, packet_number, &handle_custom_packet, &packet_number);
ck_assert_msg(ret == 0, "tox_lossless_packet_registerhandler fail %i", ret);
tox_callback_friend_lossless_packet(tox3, &handle_custom_packet, &packet_number);
uint8_t data_c[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
memset(data_c, ((uint8_t)packet_number), sizeof(data_c));
ret = tox_send_lossless_packet(tox2, 0, data_c, sizeof(data_c));
ck_assert_msg(ret == -1, "tox_send_lossless_packet bigger fail %i", ret);
ret = tox_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE);
ck_assert_msg(ret == 0, "tox_send_lossless_packet fail %i", ret);
int ret = tox_friend_send_lossless_packet(tox2, 0, data_c, sizeof(data_c), 0);
ck_assert_msg(ret == 0, "tox_friend_send_lossless_packet bigger fail %i", ret);
ret = tox_friend_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0);
ck_assert_msg(ret == 1, "tox_friend_send_lossless_packet fail %i", ret);
while (1) {
custom_packet = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (custom_packet == 1)
break;
@ -334,19 +550,18 @@ START_TEST(test_few_clients)
}
packet_number = 200;
ret = tox_lossy_packet_registerhandler(tox3, 0, packet_number, &handle_custom_packet, &packet_number);
ck_assert_msg(ret == 0, "tox_lossy_packet_registerhandler fail %i", ret);
tox_callback_friend_lossy_packet(tox3, &handle_custom_packet, &packet_number);
memset(data_c, ((uint8_t)packet_number), sizeof(data_c));
ret = tox_send_lossy_packet(tox2, 0, data_c, sizeof(data_c));
ck_assert_msg(ret == -1, "tox_send_lossy_packet bigger fail %i", ret);
ret = tox_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE);
ck_assert_msg(ret == 0, "tox_send_lossy_packet fail %i", ret);
ret = tox_friend_send_lossy_packet(tox2, 0, data_c, sizeof(data_c), 0);
ck_assert_msg(ret == 0, "tox_friend_send_lossy_packet bigger fail %i", ret);
ret = tox_friend_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0);
ck_assert_msg(ret == 1, "tox_friend_send_lossy_packet fail %i", ret);
while (1) {
custom_packet = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (custom_packet == 1)
break;
@ -356,45 +571,48 @@ START_TEST(test_few_clients)
c_sleep(50);
}
filenum = file_accepted = file_size = file_sent = sendf_ok = size_recv = 0;
printf("Starting file transfer test.\n");
file_accepted = file_size = file_recv = sendf_ok = size_recv = 0;
max_sending = UINT64_MAX;
long long unsigned int f_time = time(NULL);
tox_callback_file_data(tox3, write_file, &to_compare);
tox_callback_file_control(tox2, file_print_control, &to_compare);
tox_callback_file_control(tox3, file_print_control, &to_compare);
tox_callback_file_send_request(tox3, file_request_accept, &to_compare);
tox_callback_file_recv_chunk(tox3, write_file, &to_compare);
tox_callback_file_recv_control(tox2, file_print_control, &to_compare);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request, &to_compare);
tox_callback_file_recv_control(tox3, file_print_control, &to_compare);
tox_callback_file_recv(tox3, tox_file_receive, &to_compare);
uint64_t totalf_size = 100 * 1024 * 1024;
int fnum = tox_new_file_sender(tox2, 0, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"));
ck_assert_msg(fnum != -1, "tox_new_file_sender fail");
int fpiece_size = tox_file_data_size(tox2, 0);
uint8_t f_data[fpiece_size];
uint8_t num = 0;
memset(f_data, num, fpiece_size);
uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (uint8_t *)"Gentoo.exe",
sizeof("Gentoo.exe"), 0);
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
TOX_ERR_FILE_GET gfierr;
ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
while (1) {
file_sent = 0;
tox_do(tox1);
tox_do(tox2);
tox_do(tox3);
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (sendf_ok)
while (tox_file_send_data(tox2, 0, fnum, f_data, fpiece_size < totalf_size ? fpiece_size : totalf_size) == 0) {
if (totalf_size <= fpiece_size) {
sendf_ok = 0;
tox_file_send_control(tox2, 0, 0, fnum, TOX_FILECONTROL_FINISHED, NULL, 0);
}
++num;
memset(f_data, num, fpiece_size);
totalf_size -= fpiece_size;
}
if (file_sent && size_recv == file_size)
if (file_sending_done) {
if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
&& file_accepted == 1) {
break;
} else {
ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv,
totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, file_accepted == 1, totalf_size, size_recv,
sending_pos);
}
}
uint32_t tox1_interval = tox_do_interval(tox1);
uint32_t tox2_interval = tox_do_interval(tox2);
uint32_t tox3_interval = tox_do_interval(tox3);
uint32_t tox1_interval = tox_iteration_interval(tox1);
uint32_t tox2_interval = tox_iteration_interval(tox2);
uint32_t tox3_interval = tox_iteration_interval(tox3);
if (tox2_interval > tox3_interval) {
c_sleep(tox3_interval);
@ -405,6 +623,105 @@ START_TEST(test_few_clients)
printf("100MB file sent in %llu seconds\n", time(NULL) - f_time);
printf("Starting file streaming transfer test.\n");
file_sending_done = file_accepted = file_size = file_recv = sendf_ok = size_recv = 0;
f_time = time(NULL);
tox_callback_file_recv_chunk(tox3, write_file, &to_compare);
tox_callback_file_recv_control(tox2, file_print_control, &to_compare);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request, &to_compare);
tox_callback_file_recv_control(tox3, file_print_control, &to_compare);
tox_callback_file_recv(tox3, tox_file_receive, &to_compare);
totalf_size = UINT64_MAX;
fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), 0);
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
max_sending = 100 * 1024;
m_send_reached = 0;
while (1) {
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (file_sending_done) {
if (sendf_ok && file_recv && m_send_reached && totalf_size == file_size && size_recv == max_sending
&& sending_pos == size_recv && file_accepted == 1) {
break;
} else {
ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %u %llu %llu %llu %llu", sendf_ok, file_recv,
m_send_reached, totalf_size == file_size, size_recv == max_sending, sending_pos == size_recv, file_accepted == 1,
totalf_size, file_size,
size_recv, sending_pos);
}
}
uint32_t tox1_interval = tox_iteration_interval(tox1);
uint32_t tox2_interval = tox_iteration_interval(tox2);
uint32_t tox3_interval = tox_iteration_interval(tox3);
if (tox2_interval > tox3_interval) {
c_sleep(tox3_interval);
} else {
c_sleep(tox2_interval);
}
}
printf("Starting file 0 transfer test.\n");
file_sending_done = file_accepted = file_size = file_recv = sendf_ok = size_recv = 0;
f_time = time(NULL);
tox_callback_file_recv_chunk(tox3, write_file, &to_compare);
tox_callback_file_recv_control(tox2, file_print_control, &to_compare);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request, &to_compare);
tox_callback_file_recv_control(tox3, file_print_control, &to_compare);
tox_callback_file_recv(tox3, tox_file_receive, &to_compare);
totalf_size = 0;
fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), 0);
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
while (1) {
tox_iterate(tox1);
tox_iterate(tox2);
tox_iterate(tox3);
if (file_sending_done) {
if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
&& file_accepted == 1) {
break;
} else {
ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv,
totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, file_accepted == 1, totalf_size, size_recv,
sending_pos);
}
}
uint32_t tox1_interval = tox_iteration_interval(tox1);
uint32_t tox2_interval = tox_iteration_interval(tox2);
uint32_t tox3_interval = tox_iteration_interval(tox3);
if (tox2_interval > tox3_interval) {
c_sleep(tox3_interval);
} else {
c_sleep(tox2_interval);
}
}
printf("test_few_clients succeeded, took %llu seconds\n", time(NULL) - cur_time);
tox_kill(tox1);
@ -424,17 +741,23 @@ START_TEST(test_many_clients)
uint32_t to_comp = 974536;
for (i = 0; i < NUM_TOXES; ++i) {
toxes[i] = tox_new(0);
toxes[i] = tox_new(0, 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);
}
{
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");
}
struct {
uint16_t tox1;
uint16_t tox2;
} pairs[NUM_FRIENDS];
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
uint8_t address[TOX_ADDRESS_SIZE];
for (i = 0; i < NUM_FRIENDS; ++i) {
loop_top:
@ -446,22 +769,24 @@ loop_top:
goto loop_top;
}
tox_get_address(toxes[pairs[i].tox1], address);
int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7);
tox_self_get_address(toxes[pairs[i].tox1], address);
if (test == TOX_FAERR_ALREADYSENT) {
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(test >= 0, "Failed to add friend error code: %i", test);
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_count_friendlist(toxes[i]); ++j)
if (tox_get_friend_connection_status(toxes[i], j) == 1)
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_UDP)
++counter;
}
@ -470,7 +795,7 @@ loop_top:
}
for (i = 0; i < NUM_TOXES; ++i) {
tox_do(toxes[i]);
tox_iterate(toxes[i]);
}
c_sleep(50);
@ -486,13 +811,13 @@ END_TEST
#define NUM_GROUP_TOX 32
void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (*((uint32_t *)userdata) != 234212)
return;
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
tox_add_friend_norequest(m, public_key);
tox_friend_add_norequest(m, public_key, 0);
}
}
@ -543,24 +868,30 @@ START_TEST(test_many_group)
uint32_t to_comp = 234212;
for (i = 0; i < NUM_GROUP_TOX; ++i) {
toxes[i] = tox_new(0);
toxes[i] = tox_new(0, 0, 0, 0);
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_group_invite(toxes[i], &print_group_invite_callback, &to_comp);
}
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(toxes[NUM_GROUP_TOX - 1], address);
{
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");
}
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(toxes[NUM_GROUP_TOX - 1], address);
for (i = 0; i < NUM_GROUP_TOX; ++i) {
ck_assert_msg(tox_add_friend(toxes[i], address, (uint8_t *)"Gentoo", 7) == 0, "Failed to add friend");
ck_assert_msg(tox_friend_add(toxes[i], address, (uint8_t *)"Gentoo", 7, 0) == 0, "Failed to add friend");
tox_get_address(toxes[i], address);
tox_self_get_address(toxes[i], address);
}
while (1) {
for (i = 0; i < NUM_GROUP_TOX; ++i) {
if (tox_get_friend_connection_status(toxes[i], 0) != 1) {
if (tox_friend_get_connection_status(toxes[i], 0, 0) != TOX_CONNECTION_UDP) {
break;
}
}
@ -569,7 +900,7 @@ START_TEST(test_many_group)
break;
for (i = 0; i < NUM_GROUP_TOX; ++i) {
tox_do(toxes[i]);
tox_iterate(toxes[i]);
}
c_sleep(50);
@ -587,7 +918,7 @@ START_TEST(test_many_group)
while (1) {
for (i = 0; i < NUM_GROUP_TOX; ++i) {
tox_do(toxes[i]);
tox_iterate(toxes[i]);
}
if (!invite_counter) {
@ -625,7 +956,7 @@ START_TEST(test_many_group)
for (j = 0; j < 20; ++j) {
for (i = 0; i < NUM_GROUP_TOX; ++i) {
tox_do(toxes[i]);
tox_iterate(toxes[i]);
}
c_sleep(50);
@ -638,7 +969,7 @@ START_TEST(test_many_group)
for (j = 0; j < 10; ++j) {
for (i = 0; i < NUM_GROUP_TOX; ++i) {
tox_do(toxes[i]);
tox_iterate(toxes[i]);
}
c_sleep(50);

View File

@ -55,10 +55,10 @@ typedef struct _Status {
/* My default settings */
static ToxAvCSettings muhcaps;
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (length == 7 && memcmp("gentoo", data, 7) == 0) {
tox_add_friend_norequest(m, public_key);
tox_friend_add_norequest(m, public_key, 0);
}
}
@ -232,7 +232,7 @@ void register_callbacks(ToxAv *av, void *data)
*/
#define CALL_AND_START_LOOP(AliceCallType, BobCallType) \
{ int step = 0, running = 1; while (running) {\
tox_do(bootstrap_node); tox_do(Alice); tox_do(Bob); \
tox_iterate(bootstrap_node); tox_iterate(Alice); tox_iterate(Bob); \
toxav_do(status_control.Bob.av); toxav_do(status_control.Alice.av); \
switch ( step ) {\
case 0: /* Alice */ printf("Alice is calling...\n");\
@ -250,33 +250,35 @@ if (status_control.Alice.status == Ended && status_control.Bob.status == Ended)
START_TEST(test_AV_flows)
{
long long unsigned int cur_time = time(NULL);
Tox *bootstrap_node = tox_new(0);
Tox *Alice = tox_new(0);
Tox *Bob = tox_new(0);
Tox *bootstrap_node = tox_new(0, 0, 0, 0);
Tox *Alice = tox_new(0, 0, 0, 0);
Tox *Bob = tox_new(0, 0, 0, 0);
ck_assert_msg(bootstrap_node || Alice || Bob, "Failed to create 3 tox instances");
uint32_t to_compare = 974536;
tox_callback_friend_request(Alice, accept_friend_request, &to_compare);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(Alice, address);
int test = tox_add_friend(Bob, address, (uint8_t *)"gentoo", 7);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(Alice, address);
uint32_t test = tox_friend_add(Bob, address, (uint8_t *)"gentoo", 7, 0);
ck_assert_msg(test == 0, "Failed to add friend error code: %i", test);
uint8_t off = 1;
while (1) {
tox_do(bootstrap_node);
tox_do(Alice);
tox_do(Bob);
tox_iterate(bootstrap_node);
tox_iterate(Alice);
tox_iterate(Bob);
if (tox_isconnected(bootstrap_node) && tox_isconnected(Alice) && tox_isconnected(Bob) && off) {
if (tox_self_get_connection_status(bootstrap_node) && tox_self_get_connection_status(Alice)
&& tox_self_get_connection_status(Bob)
&& off) {
printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
off = 0;
}
if (tox_get_friend_connection_status(Alice, 0) == 1 && tox_get_friend_connection_status(Bob, 0) == 1)
if (tox_friend_get_connection_status(Alice, 0, 0) && tox_friend_get_connection_status(Bob, 0, 0))
break;
c_sleep(20);
@ -483,9 +485,9 @@ START_TEST(test_AV_flows)
int running = 1;
while (running) {
tox_do(bootstrap_node);
tox_do(Alice);
tox_do(Bob);
tox_iterate(bootstrap_node);
tox_iterate(Alice);
tox_iterate(Bob);
switch ( step ) {
case 0: /* Alice */
@ -524,9 +526,9 @@ START_TEST(test_AV_flows)
int running = 1;
while (running) {
tox_do(bootstrap_node);
tox_do(Alice);
tox_do(Bob);
tox_iterate(bootstrap_node);
tox_iterate(Alice);
tox_iterate(Bob);
toxav_do(status_control.Alice.av);
toxav_do(status_control.Bob.av);
@ -569,9 +571,9 @@ START_TEST(test_AV_flows)
int running = 1;
while (running) {
tox_do(bootstrap_node);
tox_do(Alice);
tox_do(Bob);
tox_iterate(bootstrap_node);
tox_iterate(Alice);
tox_iterate(Bob);
toxav_do(status_control.Alice.av);
toxav_do(status_control.Bob.av);

View File

@ -58,10 +58,10 @@ typedef struct _Status {
Status status_control;
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
if (length == 7 && memcmp("gentoo", data, 7) == 0) {
tox_add_friend_norequest(m, public_key);
tox_friend_add_norequest(m, public_key, 0);
}
}
@ -264,12 +264,12 @@ START_TEST(test_AV_three_calls)
// void test_AV_three_calls()
{
long long unsigned int cur_time = time(NULL);
Tox *bootstrap_node = tox_new(0);
Tox *caller = tox_new(0);
Tox *bootstrap_node = tox_new(0, 0, 0, 0);
Tox *caller = tox_new(0, 0, 0, 0);
Tox *callees[3] = {
tox_new(0),
tox_new(0),
tox_new(0),
tox_new(0, 0, 0, 0),
tox_new(0, 0, 0, 0),
tox_new(0, 0, 0, 0),
};
@ -284,37 +284,37 @@ START_TEST(test_AV_three_calls)
for ( i = 0; i < 3; i ++ ) {
uint32_t to_compare = 974536;
tox_callback_friend_request(callees[i], accept_friend_request, &to_compare);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(callees[i], address);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(callees[i], address);
int test = tox_add_friend(caller, address, (uint8_t *)"gentoo", 7);
uint32_t test = tox_friend_add(caller, address, (uint8_t *)"gentoo", 7, 0);
ck_assert_msg( test == i, "Failed to add friend error code: %i", test);
}
uint8_t off = 1;
while (1) {
tox_do(bootstrap_node);
tox_do(caller);
tox_iterate(bootstrap_node);
tox_iterate(caller);
for (i = 0; i < 3; i ++) {
tox_do(callees[i]);
tox_iterate(callees[i]);
}
if (tox_isconnected(bootstrap_node) &&
tox_isconnected(caller) &&
tox_isconnected(callees[0]) &&
tox_isconnected(callees[1]) &&
tox_isconnected(callees[2]) && off) {
if (tox_self_get_connection_status(bootstrap_node) &&
tox_self_get_connection_status(caller) &&
tox_self_get_connection_status(callees[0]) &&
tox_self_get_connection_status(callees[1]) &&
tox_self_get_connection_status(callees[2]) && off) {
printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
off = 0;
}
if (tox_get_friend_connection_status(caller, 0) == 1 &&
tox_get_friend_connection_status(caller, 1) == 1 &&
tox_get_friend_connection_status(caller, 2) == 1 )
if (tox_friend_get_connection_status(caller, 0, 0) &&
tox_friend_get_connection_status(caller, 1, 0) &&
tox_friend_get_connection_status(caller, 2, 0) )
break;
c_sleep(20);
@ -351,11 +351,11 @@ START_TEST(test_AV_three_calls)
while (call_running[0] || call_running[1] || call_running[2]) {
pthread_mutex_lock(&muhmutex);
tox_do(bootstrap_node);
tox_do(caller);
tox_do(callees[0]);
tox_do(callees[1]);
tox_do(callees[2]);
tox_iterate(bootstrap_node);
tox_iterate(caller);
tox_iterate(callees[0]);
tox_iterate(callees[1]);
tox_iterate(callees[2]);
for ( i = 0; i < 3; i++ )
toxav_do(status_control.calls[0].Caller.av);

View File

@ -106,21 +106,6 @@ tox_shell_LDADD = $(LIBSODIUM_LDFLAGS) \
-lutil
noinst_PROGRAMS += test_avatars
test_avatars_SOURCES = ../testing/test_avatars.c
test_avatars_CFLAGS = $(LIBSODIUM_CFLAGS) \
$(NACL_CFLAGS)
test_avatars_LDADD = $(LIBSODIUM_LDFLAGS) \
$(NACL_LDFLAGS) \
libtoxcore.la \
$(LIBSODIUM_LIBS) \
$(NACL_OBJECTS) \
$(NACL_LIBS)
noinst_PROGRAMS += irc_syncbot
irc_syncbot_SOURCES = ../testing/irc_syncbot.c

View File

@ -56,17 +56,18 @@
#endif
void print_message(Messenger *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_message(Messenger *m, uint32_t friendnumber, unsigned int type, const uint8_t *string, size_t length,
void *userdata)
{
printf("Message with length %u received from %u: %s \n", length, friendnumber, string);
m_sendmessage(m, friendnumber, (uint8_t *)"Test1", 6);
printf("Message with length %lu received from %u: %s \n", length, friendnumber, string);
m_send_message_generic(m, friendnumber, type, (uint8_t *)"Test1", 6, 0);
}
/* FIXME needed as print_request has to match the interface expected by
* networking_requesthandler and so cannot take a Messenger * */
static Messenger *m;
void print_request(Messenger *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void print_request(Messenger *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
printf("Friend request received from: \n");
printf("ClientID: ");
@ -79,7 +80,7 @@ void print_request(Messenger *m, const uint8_t *public_key, const uint8_t *data,
printf("%hhX", public_key[j]);
}
printf("\nOf length: %u with data: %s \n", length, data);
printf("\nOf length: %lu with data: %s \n", length, data);
if (length != sizeof("Install Gentoo")) {
return;
@ -112,7 +113,7 @@ int main(int argc, char *argv[])
Messenger_Options options = {0};
options.ipv6enabled = ipv6enabled;
m = new_messenger(&options);
m = new_messenger(&options, 0);
if ( !m ) {
fputs("Failed to allocate messenger datastructure\n", stderr);
@ -184,7 +185,7 @@ int main(int argc, char *argv[])
getname(m, num, name);
printf("%s\n", name);
m_sendmessage(m, num, (uint8_t *)"Test", 5);
m_send_message_generic(m, num, MESSAGE_NORMAL, (uint8_t *)"Test", 5, 0);
do_messenger(m);
c_sleep(30);
FILE *file = fopen("Save.bak", "wb");

View File

@ -98,7 +98,7 @@ int main(int argc, char *argv[])
for (i = r_len - 1; i != 0 && buffer[i] != '='; --i);
uint8_t tox_id[TOX_FRIEND_ADDRESS_SIZE];
uint8_t tox_id[TOX_ADDRESS_SIZE];
if (tox_decrypt_dns3_TXT(d, tox_id, buffer + i + 1, r_len - (i + 1), request_id) != 0)
return -1;
@ -106,7 +106,7 @@ int main(int argc, char *argv[])
printf("The Tox id for username %s is:\n", argv[3]);
//unsigned int i;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) {
for (i = 0; i < TOX_ADDRESS_SIZE; ++i) {
printf("%02hhX", tox_id[i]);
}

View File

@ -89,7 +89,8 @@ static void callback_group_invite(Tox *tox, int fid, uint8_t type, const uint8_t
current_group = tox_join_groupchat(tox, fid, data, length);
}
void callback_friend_message(Tox *tox, int fid, const uint8_t *message, uint16_t length, void *userdata)
void callback_friend_message(Tox *tox, uint32_t fid, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length,
void *userdata)
{
if (length == 1 && *message == 'c') {
if (tox_del_groupchat(tox, current_group) == 0)
@ -203,7 +204,7 @@ void send_irc_group(Tox *tox, uint8_t *msg, uint16_t len)
Tox *init_tox(int argc, char *argv[])
{
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
uint8_t ipv6enabled = 1; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0)
@ -215,12 +216,12 @@ Tox *init_tox(int argc, char *argv[])
exit(0);
}
Tox *tox = tox_new(0);
Tox *tox = tox_new(0, 0, 0, 0);
if (!tox)
exit(1);
tox_set_name(tox, (uint8_t *)IRC_NAME, sizeof(IRC_NAME) - 1);
tox_self_set_name(tox, (uint8_t *)IRC_NAME, sizeof(IRC_NAME) - 1, 0);
tox_callback_friend_message(tox, &callback_friend_message, 0);
tox_callback_group_invite(tox, &callback_group_invite, 0);
tox_callback_group_message(tox, &copy_groupmessage, 0);
@ -228,7 +229,7 @@ Tox *init_tox(int argc, char *argv[])
uint16_t port = atoi(argv[argvoffset + 2]);
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
int res = tox_bootstrap_from_address(tox, argv[argvoffset + 1], port, binary_string);
tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
free(binary_string);
char temp_id[128];
@ -239,10 +240,10 @@ Tox *init_tox(int argc, char *argv[])
}
uint8_t *bin_id = hex_string_to_bin(temp_id);
int num = tox_add_friend(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1);
uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0);
free(bin_id);
if (num < 0) {
if (num == UINT32_MAX) {
printf("\nSomething went wrong when adding friend.\n");
exit(1);
}
@ -342,7 +343,7 @@ int main(int argc, char *argv[])
}
}
tox_do(tox);
tox_iterate(tox);
usleep(1000 * 50);
}

View File

@ -105,55 +105,52 @@ int x, y;
int conversation_default = 0;
typedef struct {
uint8_t id[TOX_CLIENT_ID_SIZE];
uint8_t id[TOX_PUBLIC_KEY_SIZE];
uint8_t accepted;
} Friend_request;
Friend_request pending_requests[256];
uint8_t num_requests = 0;
#define NUM_FILE_SENDERS 256
#define NUM_FILE_SENDERS 64
typedef struct {
FILE *file;
uint16_t friendnum;
uint8_t filenumber;
uint8_t nextpiece[1024];
uint16_t piecelength;
uint32_t friendnum;
uint32_t filenumber;
} File_Sender;
File_Sender file_senders[NUM_FILE_SENDERS];
uint8_t numfilesenders;
void send_filesenders(Tox *m)
void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length,
void *user_data)
{
uint32_t i;
unsigned int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i) {
if (file_senders[i].file == 0)
continue;
while (1) {
if (tox_file_send_data(m, file_senders[i].friendnum, file_senders[i].filenumber, file_senders[i].nextpiece,
file_senders[i].piecelength) == -1)
break;
file_senders[i].piecelength = fread(file_senders[i].nextpiece, 1, tox_file_data_size(m, file_senders[i].friendnum),
file_senders[i].file);
if (file_senders[i].piecelength == 0) {
/* This is slow */
if (file_senders[i].file && file_senders[i].friendnum == friend_number && file_senders[i].filenumber == file_number) {
if (length == 0) {
fclose(file_senders[i].file);
file_senders[i].file = 0;
tox_file_send_control(m, file_senders[i].friendnum, 0, file_senders[i].filenumber, 3, 0, 0);
char msg[512];
sprintf(msg, "[t] %u file transfer: %u completed", file_senders[i].friendnum, file_senders[i].filenumber);
new_lines(msg);
break;
}
fseek(file_senders[i].file, position, SEEK_SET);
uint8_t data[length];
int len = fread(data, 1, length, file_senders[i].file);
tox_file_send_chunk(tox, friend_number, file_number, position, data, len, 0);
break;
}
}
}
int add_filesender(Tox *m, uint16_t friendnum, char *filename)
uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename)
{
FILE *tempfile = fopen(filename, "r");
FILE *tempfile = fopen(filename, "rb");
if (tempfile == 0)
return -1;
@ -161,15 +158,13 @@ int add_filesender(Tox *m, uint16_t friendnum, char *filename)
fseek(tempfile, 0, SEEK_END);
uint64_t filesize = ftell(tempfile);
fseek(tempfile, 0, SEEK_SET);
int filenum = tox_new_file_sender(m, friendnum, filesize, (uint8_t *)filename, strlen(filename) + 1);
uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, 0, (uint8_t *)filename,
strlen(filename), 0);
if (filenum == -1)
return -1;
file_senders[numfilesenders].file = tempfile;
file_senders[numfilesenders].piecelength = fread(file_senders[numfilesenders].nextpiece, 1, tox_file_data_size(m,
file_senders[numfilesenders].friendnum),
file_senders[numfilesenders].file);
file_senders[numfilesenders].friendnum = friendnum;
file_senders[numfilesenders].filenumber = filenum;
++numfilesenders;
@ -179,19 +174,19 @@ int add_filesender(Tox *m, uint16_t friendnum, char *filename)
#define FRADDR_TOSTR_CHUNK_LEN 8
#define FRADDR_TOSTR_BUFSIZE (TOX_FRIEND_ADDRESS_SIZE * 2 + TOX_FRIEND_ADDRESS_SIZE / FRADDR_TOSTR_CHUNK_LEN + 1)
#define FRADDR_TOSTR_BUFSIZE (TOX_ADDRESS_SIZE * 2 + TOX_ADDRESS_SIZE / FRADDR_TOSTR_CHUNK_LEN + 1)
static void fraddr_to_str(uint8_t *id_bin, char *id_str)
{
uint32_t i, delta = 0, pos_extra, sum_extra = 0;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
for (i = 0; i < TOX_ADDRESS_SIZE; i++) {
sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]);
if ((i + 1) == TOX_CLIENT_ID_SIZE)
if ((i + 1) == TOX_PUBLIC_KEY_SIZE)
pos_extra = 2 * (i + 1) + delta;
if (i >= TOX_CLIENT_ID_SIZE)
if (i >= TOX_PUBLIC_KEY_SIZE)
sum_extra |= id_bin[i];
if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) {
@ -210,14 +205,15 @@ void get_id(Tox *m, char *data)
{
sprintf(data, "[i] ID: ");
int offset = strlen(data);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, address);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(m, address);
fraddr_to_str(address, data + offset);
}
int getfriendname_terminated(Tox *m, int friendnum, char *namebuf)
{
int res = tox_get_name(m, friendnum, (uint8_t *)namebuf);
tox_friend_get_name(m, friendnum, (uint8_t *)namebuf, NULL);
int res = tox_friend_get_name_size(m, friendnum, NULL);
if (res >= 0)
namebuf[res] = 0;
@ -249,13 +245,13 @@ void new_lines(char *line)
const char ptrn_friend[] = "[i] Friend %i: %s\n+ id: %s";
const int id_str_len = TOX_FRIEND_ADDRESS_SIZE * 2 + 3;
const int id_str_len = TOX_ADDRESS_SIZE * 2 + 3;
void print_friendlist(Tox *m)
{
new_lines("[i] Friend List:");
char name[TOX_MAX_NAME_LENGTH + 1];
uint8_t fraddr_bin[TOX_FRIEND_ADDRESS_SIZE];
uint8_t fraddr_bin[TOX_ADDRESS_SIZE];
char fraddr_str[FRADDR_TOSTR_BUFSIZE];
/* account for the longest name and the longest "base" string and number (int) and id_str */
@ -264,7 +260,7 @@ void print_friendlist(Tox *m)
uint32_t i = 0;
while (getfriendname_terminated(m, i, name) != -1) {
if (!tox_get_client_id(m, i, fraddr_bin))
if (tox_friend_get_public_key(m, i, fraddr_bin, NULL))
fraddr_to_str(fraddr_bin, fraddr_str);
else
sprintf(fraddr_str, "???");
@ -347,50 +343,59 @@ void line_eval(Tox *m, char *line)
}
unsigned char *bin_string = hex_string_to_bin(temp_id);
int num = tox_add_friend(m, bin_string, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"));
TOX_ERR_FRIEND_ADD error;
uint32_t num = tox_friend_add(m, bin_string, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"), &error);
free(bin_string);
char numstring[100];
switch (num) {
case TOX_FAERR_TOOLONG:
switch (error) {
case TOX_ERR_FRIEND_ADD_TOO_LONG:
sprintf(numstring, "[i] Message is too long.");
break;
case TOX_FAERR_NOMESSAGE:
case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
sprintf(numstring, "[i] Please add a message to your request.");
break;
case TOX_FAERR_OWNKEY:
case TOX_ERR_FRIEND_ADD_OWN_KEY:
sprintf(numstring, "[i] That appears to be your own ID.");
break;
case TOX_FAERR_ALREADYSENT:
case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
sprintf(numstring, "[i] Friend request already sent.");
break;
case TOX_FAERR_UNKNOWN:
sprintf(numstring, "[i] Undefined error when adding friend.");
case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
sprintf(numstring, "[i] Address has a bad checksum.");
break;
default:
if (num >= 0) {
case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM:
sprintf(numstring, "[i] New nospam set.");
break;
case TOX_ERR_FRIEND_ADD_MALLOC:
sprintf(numstring, "[i] malloc error.");
break;
case TOX_ERR_FRIEND_ADD_NULL:
sprintf(numstring, "[i] message was NULL.");
break;
case TOX_ERR_FRIEND_ADD_OK:
sprintf(numstring, "[i] Added friend as %d.", num);
save_data(m);
} else
sprintf(numstring, "[i] Unknown error %i.", num);
break;
}
new_lines(numstring);
} else if (inpt_command == 'd') {
tox_do(m);
tox_iterate(m);
} else if (inpt_command == 'm') { //message command: /m friendnumber messsage
char *posi[1];
int num = strtoul(line + prompt_offset, posi, 0);
if (**posi != 0) {
if (tox_send_message(m, num, (uint8_t *) *posi + 1, strlen(*posi + 1)) < 1) {
if (tox_friend_send_message(m, num, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) *posi + 1, strlen(*posi + 1), NULL) < 1) {
char sss[256];
sprintf(sss, "[i] could not send message to friend num %u", num);
new_lines(sss);
@ -410,14 +415,14 @@ void line_eval(Tox *m, char *line)
}
name[i - 3] = 0;
tox_set_name(m, name, i - 2);
tox_self_set_name(m, name, i - 2, NULL);
char numstring[100];
sprintf(numstring, "[i] changed nick to %s", (char *)name);
new_lines(numstring);
} else if (inpt_command == 'l') {
print_friendlist(m);
} else if (inpt_command == 's') {
uint8_t status[TOX_MAX_STATUSMESSAGE_LENGTH];
uint8_t status[TOX_MAX_STATUS_MESSAGE_LENGTH];
size_t i, len = strlen(line);
for (i = 3; i < len; i++) {
@ -427,7 +432,7 @@ void line_eval(Tox *m, char *line)
}
status[i - 3] = 0;
tox_set_status_message(m, status, strlen((char *)status));
tox_self_set_status_message(m, status, strlen((char *)status), NULL);
char numstring[100];
sprintf(numstring, "[i] changed status to %s", (char *)status);
new_lines(numstring);
@ -439,9 +444,9 @@ void line_eval(Tox *m, char *line)
sprintf(numchar, "[i] you either didn't receive that request or you already accepted it");
new_lines(numchar);
} else {
int num = tox_add_friend_norequest(m, pending_requests[numf].id);
uint32_t num = tox_friend_add_norequest(m, pending_requests[numf].id, NULL);
if (num != -1) {
if (num != UINT32_MAX) {
pending_requests[numf].accepted = 1;
sprintf(numchar, "[i] friend request %u accepted as friend no. %d", numf, num);
new_lines(numchar);
@ -475,9 +480,9 @@ void line_eval(Tox *m, char *line)
} while ((c != 'y') && (c != 'n') && (c != EOF));
if (c == 'y') {
int res = tox_del_friend(m, numf);
int res = tox_friend_delete(m, numf, NULL);
if (res == 0)
if (res)
sprintf(msg, "[i] [%i: %s] is no longer your friend", numf, fname);
else
sprintf(msg, "[i] failed to remove friend");
@ -602,7 +607,7 @@ void line_eval(Tox *m, char *line)
if (conversation_default != 0) {
if (conversation_default > 0) {
int friendnumber = conversation_default - 1;
uint32_t res = tox_send_message(m, friendnumber, (uint8_t *)line, strlen(line));
uint32_t res = tox_friend_send_message(m, friendnumber, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *)line, strlen(line), NULL);
if (res == 0) {
char sss[128];
@ -863,20 +868,21 @@ void do_refresh()
refresh();
}
void print_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
void print_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{
new_lines("[i] received friend request with message:");
new_lines((char *)data);
char numchar[100];
sprintf(numchar, "[i] accept request with /a %u", num_requests);
new_lines(numchar);
memcpy(pending_requests[num_requests].id, public_key, TOX_CLIENT_ID_SIZE);
memcpy(pending_requests[num_requests].id, public_key, TOX_PUBLIC_KEY_SIZE);
pending_requests[num_requests].accepted = 0;
++num_requests;
do_refresh();
}
void print_message(Tox *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
void *userdata)
{
/* ensure null termination */
uint8_t null_string[length + 1];
@ -885,7 +891,7 @@ void print_message(Tox *m, int friendnumber, const uint8_t *string, uint16_t len
print_formatted_message(m, (char *)null_string, friendnumber, 0);
}
void print_nickchange(Tox *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
{
char name[TOX_MAX_NAME_LENGTH + 1];
@ -901,7 +907,7 @@ void print_nickchange(Tox *m, int friendnumber, const uint8_t *string, uint16_t
}
}
void print_statuschange(Tox *m, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_statuschange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
{
char name[TOX_MAX_NAME_LENGTH + 1];
@ -919,7 +925,7 @@ void print_statuschange(Tox *m, int friendnumber, const uint8_t *string, uint16_
static char *data_file_name = NULL;
static int load_data(Tox *m)
static Tox *load_data()
{
FILE *data_file = fopen(data_file_name, "r");
@ -936,7 +942,7 @@ static int load_data(Tox *m)
return 0;
}
tox_load(m, data, size);
Tox *m = tox_new(0, data, size, NULL);
if (fclose(data_file) < 0) {
perror("[!] fclose failed");
@ -944,10 +950,10 @@ static int load_data(Tox *m)
/* return 0; */
}
return 1;
return m;
}
return 0;
return tox_new(0, 0, 0, NULL);
}
static int save_data(Tox *m)
@ -960,9 +966,9 @@ static int save_data(Tox *m)
}
int res = 1;
size_t size = tox_size(m);
size_t size = tox_get_savedata_size(m);
uint8_t data[size];
tox_save(m, data);
tox_get_savedata(m, data);
if (fwrite(data, sizeof(uint8_t), size, data_file) != size) {
fputs("[!] could not write data file (1)!", stderr);
@ -977,13 +983,10 @@ static int save_data(Tox *m)
return res;
}
static int load_data_or_init(Tox *m, char *path)
static int save_data_file(Tox *m, char *path)
{
data_file_name = path;
if (load_data(m))
return 1;
if (save_data(m))
return 1;
@ -1125,58 +1128,94 @@ void print_groupnamelistchange(Tox *m, int groupnumber, int peernumber, uint8_t
print_groupchatpeers(m, groupnumber);
}
}
void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename,
uint16_t filename_length, void *userdata)
void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t type, uint64_t file_size,
const uint8_t *filename, size_t filename_length, void *user_data)
{
if (type != TOX_FILE_KIND_DATA) {
new_lines("Refused invalid file type.");
tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0);
return;
}
char msg[512];
sprintf(msg, "[t] %u is sending us: %s of size %llu", friendnumber, filename, (long long unsigned int)filesize);
sprintf(msg, "[t] %u is sending us: %s of size %llu", friend_number, filename, (long long unsigned int)file_size);
new_lines(msg);
if (tox_file_send_control(m, friendnumber, 1, filenumber, 0, 0, 0) == 0) {
sprintf(msg, "Accepted file transfer. (saving file as: %u.%u.bin)", friendnumber, filenumber);
if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) {
sprintf(msg, "Accepted file transfer. (saving file as: %u.%u.bin)", friend_number, file_number);
new_lines(msg);
} else
new_lines("Could not accept file transfer.");
}
void file_print_control(Tox *m, int friendnumber, uint8_t send_recieve, uint8_t filenumber, uint8_t control_type,
const uint8_t *data, uint16_t length, void *userdata)
void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
void *user_data)
{
char msg[512] = {0};
if (control_type == 0)
sprintf(msg, "[t] %u accepted file transfer: %u", friendnumber, filenumber);
else if (control_type == 3)
sprintf(msg, "[t] %u file transfer: %u completed", friendnumber, filenumber);
else
sprintf(msg, "[t] control %u received", control_type);
sprintf(msg, "[t] control %u received", control);
new_lines(msg);
if (control == TOX_FILE_CONTROL_CANCEL) {
unsigned int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i) {
/* This is slow */
if (file_senders[i].file && file_senders[i].friendnum == friend_number && file_senders[i].filenumber == file_number) {
fclose(file_senders[i].file);
file_senders[i].file = 0;
char msg[512];
sprintf(msg, "[t] %u file transfer: %u cancelled", file_senders[i].friendnum, file_senders[i].filenumber);
new_lines(msg);
}
}
}
}
void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata)
void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
size_t length, void *user_data)
{
char filename[256];
sprintf(filename, "%u.%u.bin", friendnumber, filenumber);
FILE *pFile = fopen(filename, "a");
if (tox_file_data_remaining(m, friendnumber, filenumber, 1) == 0) {
//file_control(m, friendnumber, 1, filenumber, 3, 0, 0);
if (length == 0) {
char msg[512];
sprintf(msg, "[t] %u file transfer: %u completed", friendnumber, filenumber);
new_lines(msg);
return;
}
char filename[256];
sprintf(filename, "%u.%u.bin", friendnumber, filenumber);
FILE *pFile = fopen(filename, "r+b");
if (pFile == NULL)
pFile = fopen(filename, "wb");
fseek(pFile, position, SEEK_SET);
if (fwrite(data, length, 1, pFile) != 1)
new_lines("Error writing to file");
fclose(pFile);
}
void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata)
{
if (status)
printf("\nOther went online.\n");
else {
printf("\nOther went offline.\n");
unsigned int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i)
if (file_senders[i].file != 0 && file_senders[i].friendnum == friendnumber) {
fclose(file_senders[i].file);
file_senders[i].file = 0;
}
}
}
char timeout_getch(Tox *m)
{
char c;
int slpval = tox_do_interval(m);
int slpval = tox_iteration_interval(m);
fd_set fds;
FD_ZERO(&fds);
@ -1214,7 +1253,7 @@ int main(int argc, char *argv[])
}
/* let user override default by cmdline */
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
uint8_t ipv6enabled = 1; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0)
@ -1231,25 +1270,28 @@ int main(int argc, char *argv[])
if (!strcmp(argv[argc - 2], "-f"))
filename = argv[argc - 1];
m = tox_new(0);
data_file_name = filename;
m = load_data();
if ( !m ) {
fputs("Failed to allocate Messenger datastructure", stderr);
exit(0);
}
load_data_or_init(m, filename);
save_data_file(m, filename);
tox_callback_friend_request(m, print_request, NULL);
tox_callback_friend_message(m, print_message, NULL);
tox_callback_name_change(m, print_nickchange, NULL);
tox_callback_status_message(m, print_statuschange, NULL);
tox_callback_friend_name(m, print_nickchange, NULL);
tox_callback_friend_status_message(m, print_statuschange, NULL);
tox_callback_group_invite(m, print_invite, NULL);
tox_callback_group_message(m, print_groupmessage, NULL);
tox_callback_file_data(m, write_file, NULL);
tox_callback_file_control(m, file_print_control, NULL);
tox_callback_file_send_request(m, file_request_accept, NULL);
tox_callback_file_recv_chunk(m, write_file, NULL);
tox_callback_file_recv_control(m, file_print_control, NULL);
tox_callback_file_recv(m, file_request_accept, NULL);
tox_callback_file_chunk_request(m, tox_file_chunk_request, NULL);
tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL);
tox_callback_friend_connection_status(m, print_online, NULL);
initscr();
noecho();
@ -1263,7 +1305,7 @@ int main(int argc, char *argv[])
uint16_t port = atoi(argv[argvoffset + 2]);
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
int res = tox_bootstrap_from_address(m, argv[argvoffset + 1], port, binary_string);
int res = tox_bootstrap(m, argv[argvoffset + 1], port, binary_string, NULL);
if (!res) {
printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
@ -1275,7 +1317,8 @@ int main(int argc, char *argv[])
new_lines("[i] change username with /n");
uint8_t name[TOX_MAX_NAME_LENGTH + 1];
uint16_t namelen = tox_get_self_name(m, name);
tox_self_get_name(m, name);
uint16_t namelen = tox_self_get_name_size(m);
name[namelen] = 0;
if (namelen > 0) {
@ -1288,7 +1331,7 @@ int main(int argc, char *argv[])
while (1) {
if (on == 0) {
if (tox_isconnected(m)) {
if (tox_self_get_connection_status(m)) {
new_lines("[i] connected to DHT");
on = 1;
} else {
@ -1296,15 +1339,12 @@ int main(int argc, char *argv[])
if (timestamp0 + 10 < timestamp1) {
timestamp0 = timestamp1;
tox_bootstrap_from_address(m, argv[argvoffset + 1], port, binary_string);
tox_bootstrap(m, argv[argvoffset + 1], port, binary_string, NULL);
}
}
}
send_filesenders(m);
tox_do(m);
tox_iterate(m);
do_refresh();
int c = timeout_getch(m);
@ -1320,11 +1360,12 @@ int main(int argc, char *argv[])
} else if (c == 8 || c == 127) {
input_line[strlen(input_line) - 1] = '\0';
} else if (isalnum(c) || ispunct(c) || c == ' ') {
strcpy(input_line, appender(input_line, (char) c));
appender(input_line, (char) c);
}
}
free(binary_string);
save_data_file(m, filename);
tox_kill(m);
endwin();
return 0;

View File

@ -1,755 +0,0 @@
/*
* A bot to test Tox avatars
*
* Usage: ./test_avatars <data dir>
*
* Connects to the Tox network, publishes our avatar, requests our friends
* avatars and, if available, saves them to a local cache.
* This bot automatically accepts any friend request.
*
*
* Data dir MUST have:
*
* - A file named "data" (named accordingly to STS Draft v0.1.0) with
* user id, friends, bootstrap data, etc. from a previously configured
* Tox session; use a client (eg. toxic) to configure it, add friends,
* etc.
*
* Data dir MAY have:
*
* - A directory named "avatars" with the user's avatar and cached avatars.
* The user avatar must be named in the format: "<uppercase pub key>.png"
*
*
* The bot will answer to these commands:
*
* !debug-on - Enable extended debug messages
* !debug-off - Disenable extended debug messages
* !set-avatar - Set our avatar from "avatars/<USERID>.png"
* !remove-avatar - Remove our avatar
*
*/
#define DATA_FILE_NAME "data"
#define AVATAR_DIR_NAME "avatars"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../toxcore/tox.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdbool.h>
#include <limits.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
/* Basic debug utils */
#define DEBUG(format, ...) debug_printf("DEBUG: %s:%d %s: " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
static bool print_debug_msgs = true;
static void debug_printf(const char *fmt, ...)
{
if (print_debug_msgs == true) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
/* ------------ Avatar cache managenment functions ------------ */
typedef struct {
uint8_t format;
char *suffix;
} avatar_format_data_t;
static const avatar_format_data_t avatar_formats[] = {
/* In order of preference */
{ TOX_AVATAR_FORMAT_PNG, "png" },
{ TOX_AVATAR_FORMAT_NONE, NULL }, /* Must be the last one */
};
static void set_avatar(Tox *tox, const char *base_dir);
static char *get_avatar_suffix_from_format(uint8_t format)
{
int i;
for (i = 0; avatar_formats[i].format != TOX_AVATAR_FORMAT_NONE; i++)
if (avatar_formats[i].format == format)
return avatar_formats[i].suffix;
return NULL;
}
/* Load avatar data from a file into a memory buffer 'buf'.
* buf must have at least TOX_MAX_AVATAR_DATA_LENGTH bytes
* Returns the length of the data sucess or < 0 on error
*/
static int load_avatar_data(char *fname, uint8_t *buf)
{
FILE *fp = fopen(fname, "rb");
if (fp == NULL)
return -1; /* Error */
size_t n = fread(buf, 1, TOX_AVATAR_MAX_DATA_LENGTH, fp);
int ret;
if (ferror(fp) != 0 || n == 0)
ret = -1; /* Error */
else
ret = n;
fclose(fp);
return ret;
}
/* Save avatar data to a file */
static int save_avatar_data(char *fname, uint8_t *data, uint32_t len)
{
FILE *fp = fopen(fname, "wb");
if (fp == NULL)
return -1; /* Error */
int ret = 0; /* Ok */
if (fwrite(data, 1, len, fp) != len)
ret = -1; /* Error */
if (fclose(fp) != 0)
ret = -1; /* Error */
return ret;
}
static void byte_to_hex_str(const uint8_t *buf, const size_t buflen, char *dst)
{
const char *hex_chars = "0123456789ABCDEF";
size_t i = 0;
size_t j = 0;
while (i < buflen) {
dst[j++] = hex_chars[(buf[i] >> 4) & 0xf];
dst[j++] = hex_chars[buf[i] & 0xf];
i++;
}
dst[j++] = '\0';
}
/* Make the cache file name for an avatar of the given format for the given
* public key.
*/
static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir,
const uint8_t format, uint8_t *public_key)
{
char public_key_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
byte_to_hex_str(public_key, TOX_PUBLIC_KEY_SIZE, public_key_str);
const char *suffix = get_avatar_suffix_from_format(format);
if (suffix == NULL)
return -1; /* Error */
int n = snprintf(dst, dst_len, "%s/%s/%s.%s", base_dir, AVATAR_DIR_NAME,
public_key_str, suffix);
dst[dst_len - 1] = '\0';
if (n >= dst_len)
return -1; /* Error: Output truncated */
return 0; /* Ok */
}
/* Load a cached avatar into the buffer 'data' (which must be at least
* TOX_MAX_AVATAR_DATA_LENGTH bytes long). Gets the file name from client
* id and the given data format.
* Returns 0 on success, or -1 on error.
*/
static int load_user_avatar(Tox *tox, char *base_dir, int friendnum,
uint8_t format, uint8_t *hash, uint8_t *data, uint32_t *datalen)
{
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
if (tox_get_client_id(tox, friendnum, addr) != 0) {
DEBUG("Bad client id, friendnumber=%d", friendnum);
return -1;
}
char path[PATH_MAX];
int ret = make_avatar_file_name(path, sizeof(path), base_dir, format, addr);
if (ret != 0) {
DEBUG("Can't create an file name for this user/avatar.");
return -1;
}
ret = load_avatar_data(path, data);
if (ret < 0) {
DEBUG("Failed to load avatar data.");
return -1;
}
*datalen = ret;
tox_hash(hash, data, *datalen);
return 0;
}
/* Save a user avatar into the cache. Gets the file name from the public key
* and the given data format.
* Returns 0 on success, or -1 on error.
*/
static int save_user_avatar(Tox *tox, char *base_dir, int friendnum,
uint8_t format, uint8_t *data, uint32_t datalen)
{
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
if (tox_get_client_id(tox, friendnum, addr) != 0) {
DEBUG("Bad client id, friendnumber=%d", friendnum);
return -1;
}
char path[PATH_MAX];
int ret = make_avatar_file_name(path, sizeof(path), base_dir, format, addr);
if (ret != 0) {
DEBUG("Can't create a file name for this user/avatar");
return -1;
}
return save_avatar_data(path, data, datalen);
}
/* Delete all cached avatars for a given user */
static int delete_user_avatar(Tox *tox, char *base_dir, int friendnum)
{
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
if (tox_get_client_id(tox, friendnum, addr) != 0) {
DEBUG("Bad client id, friendnumber=%d", friendnum);
return -1;
}
char path[PATH_MAX];
/* This iteration is dumb and inefficient */
int i;
for (i = 0; avatar_formats[i].format != TOX_AVATAR_FORMAT_NONE; i++) {
int ret = make_avatar_file_name(path, sizeof(path), base_dir,
avatar_formats[i].format, addr);
if (ret != 0) {
DEBUG("Failed to create avatar path for friend #%d, format %d\n",
friendnum, avatar_formats[i].format);
continue;
}
if (unlink(path) == 0)
printf("Avatar file %s deleted.\n", path);
}
return 0;
}
/* ------------ Protocol callbacks ------------ */
static void friend_status_cb(Tox *tox, int n, uint8_t status, void *ud)
{
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
if (tox_get_client_id(tox, n, addr) == 0) {
byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
printf("Receiving status from %s: %u\n", addr_str, status);
}
}
static void friend_avatar_info_cb(Tox *tox, int32_t n, uint8_t format, uint8_t *hash, void *ud)
{
char *base_dir = (char *) ud;
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
char hash_str[2 * TOX_HASH_LENGTH + 1];
if (tox_get_client_id(tox, n, addr) == 0) {
byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
printf("Receiving avatar information from %s.\n", addr_str);
} else {
DEBUG("tox_get_client_id failed");
printf("Receiving avatar information from friend number %u.\n", n);
}
byte_to_hex_str(hash, TOX_HASH_LENGTH, hash_str);
DEBUG("format=%u, hash=%s", format, hash_str);
if (format == TOX_AVATAR_FORMAT_NONE) {
printf(" -> User do not have an avatar.\n");
/* User have no avatar anymore, delete it from our cache */
delete_user_avatar(tox, base_dir, n);
} else {
/* Check the hash of the currently cached user avatar
* WARNING: THIS IS ONLY AN EXAMPLE!
*
* Real clients should keep the hashes in memory (eg. in the object
* used to represent a friend in the friend list) and do not access
* the file system or do anything resource intensive in reply of
* these events.
*/
uint32_t cur_av_len;
uint8_t cur_av_data[TOX_AVATAR_MAX_DATA_LENGTH];
uint8_t cur_av_hash[TOX_HASH_LENGTH];
int ret;
ret = load_user_avatar(tox, base_dir, n, format, cur_av_hash, cur_av_data, &cur_av_len);
if (ret != 0
&& memcpy(cur_av_hash, hash, TOX_HASH_LENGTH) != 0) {
printf(" -> Cached avatar is outdated. Requesting avatar data.\n");
tox_request_avatar_data(tox, n);
} else {
printf(" -> Cached avatar is still updated.\n");
}
}
}
static void friend_avatar_data_cb(Tox *tox, int32_t n, uint8_t format,
uint8_t *hash, uint8_t *data, uint32_t datalen, void *ud)
{
char *base_dir = (char *) ud;
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
char hash_str[2 * TOX_HASH_LENGTH + 1];
if (tox_get_client_id(tox, n, addr) == 0) {
byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
printf("Receiving avatar data from %s.\n", addr_str);
} else {
DEBUG("tox_get_client_id failed");
printf("Receiving avatar data from friend number %u.\n", n);
}
byte_to_hex_str(hash, TOX_HASH_LENGTH, hash_str);
DEBUG("format=%u, datalen=%d, hash=%s\n", format, datalen, hash_str);
delete_user_avatar(tox, base_dir, n);
if (format != TOX_AVATAR_FORMAT_NONE) {
int ret = save_user_avatar(tox, base_dir, n, format, data, datalen);
if (ret == 0)
printf(" -> Avatar updated in the cache.\n");
else
printf(" -> Failed to save user avatar.\n");
}
}
static void friend_msg_cb(Tox *tox, int n, const uint8_t *msg, uint16_t len, void *ud)
{
const char *base_dir = (char *) ud;
const char *msg_str = (char *) msg;
uint8_t addr[TOX_PUBLIC_KEY_SIZE];
char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
if (tox_get_client_id(tox, n, addr) == 0) {
byte_to_hex_str(addr, TOX_FRIEND_ADDRESS_SIZE, addr_str);
printf("Receiving message from %s:\n %s\n", addr_str, msg);
}
/* Handle bot commands for the tests */
char *reply_ptr = NULL;
if (strstr(msg_str, "!debug-on") != NULL) {
print_debug_msgs = true;
reply_ptr = "Debug enabled.";
} else if (strstr(msg_str, "!debug-off") != NULL) {
print_debug_msgs = false;
reply_ptr = "Debug disabled.";
} else if (strstr(msg_str, "!set-avatar") != NULL) {
set_avatar(tox, base_dir);
reply_ptr = "Setting image avatar";
} else if (strstr(msg_str, "!remove-avatar") != NULL) {
int r = tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0);
DEBUG("tox_set_avatar returned %d", r);
reply_ptr = "Removing avatar";
}
/* Add more useful commands here: add friend, etc. */
char reply[TOX_MAX_MESSAGE_LENGTH];
int reply_len;
if (reply_ptr)
reply_len = snprintf(reply, sizeof(reply), "%s", reply_ptr);
else
reply_len = snprintf(reply, sizeof(reply),
"No command found in message: %s", msg);
reply[sizeof(reply) - 1] = '\0';
printf(" -> Reply: %s\n", reply);
tox_send_message(tox, n, (uint8_t *) reply, reply_len);
}
static void friend_request_cb(Tox *tox, const uint8_t *public_key,
const uint8_t *data, uint16_t length, void *ud)
{
char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
byte_to_hex_str(public_key, TOX_PUBLIC_KEY_SIZE, addr_str);
printf("Accepting friend request from %s.\n %s\n", addr_str, data);
tox_add_friend_norequest(tox, public_key);
}
static void set_avatar(Tox *tox, const char *base_dir)
{
uint8_t addr[TOX_FRIEND_ADDRESS_SIZE];
char path[PATH_MAX];
uint8_t buf[2 * TOX_AVATAR_MAX_DATA_LENGTH];
tox_get_address(tox, addr);
int i;
for (i = 0; ; i++) {
if (avatar_formats[i].format == TOX_AVATAR_FORMAT_NONE) {
tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0);
printf("No avatar file found, setting to NONE.\n");
break;
} else {
int ret = make_avatar_file_name(path, sizeof(path), base_dir,
avatar_formats[i].format, addr);
if (ret < 0) {
printf("Failed to generate avatar file name.\n");
return;
}
int len = load_avatar_data(path, buf);
if (len < 0) {
printf("Failed to load avatar data from file: %s\n", path);
continue;
}
if (len > TOX_AVATAR_MAX_DATA_LENGTH) {
printf("Avatar file %s is too big (more than %d bytes)",
path, TOX_AVATAR_MAX_DATA_LENGTH);
return;
}
ret = tox_set_avatar(tox, avatar_formats[i].format, buf, len);
DEBUG("tox_set_avatar returned=%d", ret);
if (ret == 0)
printf("Setting avatar from %s (%d bytes).\n", path, len);
else
printf("Error setting avatar from %s.\n", path);
return;
}
}
}
static void print_avatar_info(Tox *tox)
{
uint8_t format;
uint8_t data[TOX_AVATAR_MAX_DATA_LENGTH];
uint8_t hash[TOX_HASH_LENGTH];
uint32_t data_length;
char hash_str[2 * TOX_HASH_LENGTH + 1];
int ret = tox_get_self_avatar(tox, &format, data, &data_length, sizeof(data), hash);
DEBUG("tox_get_self_avatar returned %d", ret);
DEBUG("format: %d, data_length: %d", format, data_length);
byte_to_hex_str(hash, TOX_HASH_LENGTH, hash_str);
DEBUG("hash: %s", hash_str);
}
/* ------------ Initialization functions ------------ */
/* Create directory to store tha avatars. Returns 0 if it was sucessfuly
* created or already existed. Returns -1 on error.
*/
static int create_avatar_diretory(const char *base_dir)
{
char path[PATH_MAX];
int n = snprintf(path, sizeof(path), "%s/%s", base_dir, AVATAR_DIR_NAME);
path[sizeof(path) - 1] = '\0';
if (n >= sizeof(path))
return -1;
if (mkdir(path, 0755) == 0) {
return 0; /* Done */
} else if (errno == EEXIST) {
/* Check if the existing path is a directory */
struct stat st;
if (stat(path, &st) != 0) {
perror("stat()ing avatar directory");
return -1;
}
if (S_ISDIR(st.st_mode))
return 0;
}
return -1; /* Error */
}
static void *load_bootstrap_data(const char *base_dir, uint32_t *len)
{
char path[PATH_MAX];
int n = snprintf(path, sizeof(path), "%s/%s", base_dir, DATA_FILE_NAME);
path[sizeof(path) - 1] = '\0';
if (n >= sizeof(path)) {
printf("Load error: path %s too long\n", path);
return NULL;
}
/* We should be using POSIX functions here, but let's try to be
* compatible with Windows.
*/
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
printf("fatal error: file %s not found.\n", path);
return NULL;
}
if (fseek(fp, 0, SEEK_END) != 0) {
printf("seek fail\n");
fclose(fp);
return NULL;
}
int32_t flen = ftell(fp);
if (flen < 8 || flen > 2e6) {
printf("Fatal error: file %s have %u bytes. Out of acceptable range.\n", path, flen);
fclose(fp);
return NULL;
}
if (fseek(fp, 0, SEEK_SET) != 0) {
printf("seek fail\n");
fclose(fp);
return NULL;
}
void *buf = malloc(flen);
if (buf == NULL) {
printf("malloc failed, %u bytes", flen);
fclose(fp);
return NULL;
}
*len = fread(buf, 1, flen, fp);
fclose(fp);
if (*len != flen) {
printf("fatal: %s have %u bytes, read only %u\n", path, flen, *len);
free(buf);
return NULL;
}
printf("bootstrap data loaded from %s (%u bytes)\n", path, flen);
return buf;
}
static int save_bootstrap_data(Tox *tox, const char *base_dir)
{
char path[PATH_MAX];
int n = snprintf(path, sizeof(path), "%s/%s", base_dir, DATA_FILE_NAME);
path[sizeof(path) - 1] = '\0';
if (n >= sizeof(path)) {
printf("Save error: path %s too long\n", path);
return -1;
}
char path_tmp[PATH_MAX];
n = snprintf(path_tmp, sizeof(path_tmp), "%s.tmp", path);
path_tmp[sizeof(path_tmp) - 1] = '\0';
if (n >= sizeof(path_tmp)) {
printf("error: path %s too long\n", path);
return -1;
}
uint32_t len = tox_size(tox);
if (len < 8 || len > 2e6) {
printf("save data length == %u, out of acceptable range\n", len);
return -1;
}
void *buf = malloc(len);
if (buf == NULL) {
printf("save data: malloc failed\n");
return -1;
}
tox_save(tox, buf);
FILE *fp = fopen(path_tmp, "wb");
if (fp == NULL) {
printf("Error saving data: can't open %s\n", path_tmp);
free(buf);
return -1;
}
if (fwrite(buf, 1, len, fp) != len) {
printf("Error writing data to %s\n", path_tmp);
free(buf);
fclose(fp);
return -1;
}
free(buf);
if (fclose(fp) != 0) {
printf("Error writing data to %s\n", path_tmp);
return -1;
}
if (rename(path_tmp, path) != 0) {
printf("Error renaming %s to %s\n", path_tmp, path);
return -1;
}
printf("Bootstrap data saved to %s\n", path);
return 0; /* Done */
}
int main(int argc, char *argv[])
{
int ret;
if (argc != 2) {
printf("usage: %s <data dir>\n", argv[0]);
return 1;
}
char *base_dir = argv[1];
if (create_avatar_diretory(base_dir) != 0)
printf("Error creating avatar directory.\n");
Tox *tox = tox_new(NULL);
uint32_t len;
void *data = load_bootstrap_data(base_dir, &len);
if (data == NULL)
return 1;
ret = tox_load(tox, data, len);
free(data);
if (ret == 0) {
printf("Tox initialized\n");
} else {
printf("Fatal: tox_load returned %d\n", ret);
return 1;
}
tox_callback_connection_status(tox, friend_status_cb, NULL);
tox_callback_friend_message(tox, friend_msg_cb, base_dir);
tox_callback_friend_request(tox, friend_request_cb, NULL);
tox_callback_avatar_info(tox, friend_avatar_info_cb, base_dir);
tox_callback_avatar_data(tox, friend_avatar_data_cb, base_dir);
uint8_t addr[TOX_FRIEND_ADDRESS_SIZE];
char addr_str[2 * TOX_FRIEND_ADDRESS_SIZE + 1];
tox_get_address(tox, addr);
byte_to_hex_str(addr, TOX_FRIEND_ADDRESS_SIZE, addr_str);
printf("Using local tox address: %s\n", addr_str);
#ifdef TEST_SET_RESET_AVATAR
printf("Printing default avatar information:\n");
print_avatar_info(tox);
printf("Setting a new avatar:\n");
set_avatar(tox, base_dir);
print_avatar_info(tox);
printf("Removing the avatar we just set:\n");
tox_avatar(tox, TOX_AVATARFORMAT_NONE, NULL, 0);
print_avatar_info(tox);
printf("Setting that avatar again:\n");
#endif /* TEST_SET_RESET_AVATAR */
set_avatar(tox, base_dir);
print_avatar_info(tox);
bool waiting = true;
time_t last_save = time(0);
while (1) {
if (tox_isconnected(tox) && waiting) {
printf("DHT connected.\n");
waiting = false;
}
tox_do(tox);
time_t now = time(0);
if (now - last_save > 120) {
save_bootstrap_data(tox, base_dir);
last_save = now;
}
usleep(500000);
}
return 0;
}

View File

@ -45,15 +45,16 @@
#define c_sleep(x) usleep(1000*x)
void print_online(Tox *tox, int friendnumber, uint8_t status, void *userdata)
void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata)
{
if (status == 1)
if (status)
printf("\nOther went online.\n");
else
printf("\nOther went offline.\n");
}
void print_message(Tox *tox, int friendnumber, const uint8_t *string, uint16_t length, void *userdata)
void print_message(Tox *tox, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
void *userdata)
{
int master = *((int *)userdata);
write(master, string, length);
@ -62,7 +63,7 @@ void print_message(Tox *tox, int friendnumber, const uint8_t *string, uint16_t l
int main(int argc, char *argv[])
{
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
uint8_t ipv6enabled = 1; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0)
@ -94,14 +95,14 @@ int main(int argc, char *argv[])
printf("error setting flags\n");
}
Tox *tox = tox_new(0);
tox_callback_connection_status(tox, print_online, NULL);
Tox *tox = tox_new(0, 0, 0, 0);
tox_callback_friend_connection_status(tox, print_online, NULL);
tox_callback_friend_message(tox, print_message, master);
uint16_t port = atoi(argv[argvoffset + 2]);
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
int res = tox_bootstrap_from_address(tox, argv[argvoffset + 1], port, binary_string);
int res = tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
free(binary_string);
if (!res) {
@ -109,11 +110,11 @@ int main(int argc, char *argv[])
exit(1);
}
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox, address);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox, address);
uint32_t i;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
for (i = 0; i < TOX_ADDRESS_SIZE; i++) {
printf("%02X", address[i]);
}
@ -125,10 +126,10 @@ int main(int argc, char *argv[])
}
uint8_t *bin_id = hex_string_to_bin(temp_id);
int num = tox_add_friend(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"));
uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"), 0);
free(bin_id);
if (num < 0) {
if (num == UINT32_MAX) {
printf("\nSomething went wrong when adding friend.\n");
return 1;
}
@ -136,22 +137,22 @@ int main(int argc, char *argv[])
uint8_t notconnected = 1;
while (1) {
if (tox_isconnected(tox) && notconnected) {
if (tox_self_get_connection_status(tox) && notconnected) {
printf("\nDHT connected.\n");
notconnected = 0;
}
while (tox_get_friend_connection_status(tox, num) == 1) {
while (tox_friend_get_connection_status(tox, num, 0)) {
uint8_t buf[TOX_MAX_MESSAGE_LENGTH];
ret = read(*master, buf, sizeof(buf));
if (ret <= 0)
break;
tox_send_message(tox, num, buf, ret);
tox_friend_send_message(tox, num, TOX_MESSAGE_TYPE_NORMAL, buf, ret, 0);
}
tox_do(tox);
tox_iterate(tox);
c_sleep(1);
}

View File

@ -46,43 +46,39 @@
#define NUM_FILE_SENDERS 256
typedef struct {
FILE *file;
uint16_t friendnum;
uint8_t filenumber;
uint8_t nextpiece[1400];
uint16_t piecelength;
uint32_t friendnum;
uint32_t filenumber;
} File_t;
File_t file_senders[NUM_FILE_SENDERS];
File_t file_recv[NUM_FILE_SENDERS];
uint8_t numfilesenders;
void send_filesenders(Tox *m)
void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length,
void *user_data)
{
uint32_t i;
unsigned int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i) {
if (file_senders[i].file == 0)
continue;
while (1) {
if (tox_file_send_data(m, file_senders[i].friendnum, file_senders[i].filenumber, file_senders[i].nextpiece,
file_senders[i].piecelength) != 0)
break;
file_senders[i].piecelength = fread(file_senders[i].nextpiece, 1, tox_file_data_size(m, file_senders[i].friendnum),
file_senders[i].file);
if (file_senders[i].piecelength == 0) {
/* This is slow */
if (file_senders[i].file && file_senders[i].friendnum == friend_number && file_senders[i].filenumber == file_number) {
if (length == 0) {
fclose(file_senders[i].file);
file_senders[i].file = 0;
printf("[t] %u file transfer: %u completed %i\n", file_senders[i].friendnum, file_senders[i].filenumber,
tox_file_send_control(m, file_senders[i].friendnum, 0, file_senders[i].filenumber, TOX_FILECONTROL_FINISHED, 0, 0));
printf("[t] %u file transfer: %u completed\n", file_senders[i].friendnum, file_senders[i].filenumber);
break;
}
fseek(file_senders[i].file, position, SEEK_SET);
uint8_t data[length];
int len = fread(data, 1, length, file_senders[i].file);
tox_file_send_chunk(tox, friend_number, file_number, position, data, len, 0);
break;
}
}
}
int add_filesender(Tox *m, uint16_t friendnum, char *filename)
uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename)
{
FILE *tempfile = fopen(filename, "rb");
@ -92,22 +88,20 @@ int add_filesender(Tox *m, uint16_t friendnum, char *filename)
fseek(tempfile, 0, SEEK_END);
uint64_t filesize = ftell(tempfile);
fseek(tempfile, 0, SEEK_SET);
int filenum = tox_new_file_sender(m, friendnum, filesize, (uint8_t *)filename, strlen(filename) + 1);
uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, 0, (uint8_t *)filename,
strlen(filename), 0);
if (filenum == -1)
return -1;
file_senders[numfilesenders].file = tempfile;
file_senders[numfilesenders].piecelength = fread(file_senders[numfilesenders].nextpiece, 1, tox_file_data_size(m,
file_senders[numfilesenders].friendnum),
file_senders[numfilesenders].file);
file_senders[numfilesenders].friendnum = friendnum;
file_senders[numfilesenders].filenumber = filenum;
++numfilesenders;
return filenum;
}
void kill_filesender(Tox *m, uint8_t filenum)
void kill_filesender(Tox *m, uint32_t filenum)
{
uint32_t i;
@ -130,9 +124,15 @@ int not_sending()
static char path[1024];
void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename,
uint16_t filename_length, void *userdata)
void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t type, uint64_t file_size,
const uint8_t *filename, size_t filename_length, void *user_data)
{
if (type != TOX_FILE_KIND_DATA) {
printf("Refused invalid file type.");
tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0);
return;
}
char fullpath[1024];
uint32_t i;
uint16_t rm = 0;
@ -151,58 +151,87 @@ void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t
if (tempfile != 0) {
fclose(tempfile);
tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_KILL, 0, 0);
tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0);
return;
}
file_recv[filenumber].file = fopen(fullpath, "wb");
uint8_t file_index = (file_number >> 16) - 1;
file_recv[file_index].file = fopen(fullpath, "wb");
if (file_recv[filenumber].file == 0) {
tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_KILL, 0, 0);
if (file_recv[file_index].file == 0) {
tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0);
return;
}
if (tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) {
if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) {
printf("Accepted file transfer. (file: %s)\n", fullpath);
}
}
void file_print_control(Tox *m, int friendnumber, uint8_t recieve_send, uint8_t filenumber, uint8_t control_type,
const uint8_t *data,
uint16_t length, void *userdata)
void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
void *user_data)
{
if (recieve_send == 1 && (control_type == TOX_FILECONTROL_KILL || control_type == TOX_FILECONTROL_FINISHED)) {
kill_filesender(m, filenumber);
if (file_number < (1 << 15) && (control == TOX_FILE_CONTROL_CANCEL)) {
kill_filesender(tox, file_number);
return;
}
if (recieve_send == 0 && (control_type == TOX_FILECONTROL_KILL || control_type == TOX_FILECONTROL_FINISHED)) {
fclose(file_recv[filenumber].file);
if (file_number > (1 << 15) && (control == TOX_FILE_CONTROL_CANCEL)) {
uint8_t file_index = (file_number >> 16) - 1;
fclose(file_recv[file_index].file);
printf("File closed\n");
file_recv[filenumber].file = 0;
file_recv[file_index].file = 0;
return;
}
}
void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata)
void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
size_t length, void *user_data)
{
if (file_recv[filenumber].file != 0)
if (fwrite(data, length, 1, file_recv[filenumber].file) != 1)
uint8_t file_index = (filenumber >> 16) - 1;
if (length == 0) {
fclose(file_recv[file_index].file);
printf("File closed\n");
file_recv[file_index].file = 0;
printf("%u file transfer: %u completed\n", friendnumber, filenumber);
return;
}
if (file_recv[file_index].file != 0) {
fseek(file_recv[file_index].file, position, SEEK_SET);
if (fwrite(data, length, 1, file_recv[file_index].file) != 1)
printf("Error writing data\n");
}
}
void print_online(Tox *tox, int friendnumber, uint8_t status, void *userdata)
void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata)
{
if (status == 1)
if (status)
printf("\nOther went online.\n");
else
else {
printf("\nOther went offline.\n");
unsigned int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i) {
if (file_senders[i].file != 0) {
fclose(file_senders[i].file);
file_senders[i].file = 0;
}
if (file_recv[i].file != 0) {
fclose(file_recv[i].file);
file_recv[i].file = 0;
}
}
}
}
int main(int argc, char *argv[])
{
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
uint8_t ipv6enabled = 1; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0)
@ -214,15 +243,16 @@ int main(int argc, char *argv[])
exit(0);
}
Tox *tox = tox_new(0);
tox_callback_file_data(tox, write_file, NULL);
tox_callback_file_control(tox, file_print_control, NULL);
tox_callback_file_send_request(tox, file_request_accept, NULL);
tox_callback_connection_status(tox, print_online, NULL);
Tox *tox = tox_new(0, 0, 0, 0);
tox_callback_file_recv_chunk(tox, write_file, NULL);
tox_callback_file_recv_control(tox, file_print_control, NULL);
tox_callback_file_recv(tox, file_request_accept, NULL);
tox_callback_file_chunk_request(tox, tox_file_chunk_request, NULL);
tox_callback_friend_connection_status(tox, print_online, NULL);
uint16_t port = atoi(argv[argvoffset + 2]);
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
int res = tox_bootstrap_from_address(tox, argv[argvoffset + 1], port, binary_string);
int res = tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
free(binary_string);
if (!res) {
@ -230,11 +260,11 @@ int main(int argc, char *argv[])
exit(1);
}
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox, address);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox, address);
uint32_t i;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
for (i = 0; i < TOX_ADDRESS_SIZE; i++) {
printf("%02X", address[i]);
}
@ -246,10 +276,10 @@ int main(int argc, char *argv[])
}
uint8_t *bin_id = hex_string_to_bin(temp_id);
int num = tox_add_friend(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"));
uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"), 0);
free(bin_id);
if (num < 0) {
if (num == UINT32_MAX) {
printf("\nSomething went wrong when adding friend.\n");
return 1;
}
@ -260,12 +290,12 @@ int main(int argc, char *argv[])
uint8_t notconnected = 1;
while (1) {
if (tox_isconnected(tox) && notconnected) {
if (tox_self_get_connection_status(tox) && notconnected) {
printf("\nDHT connected.\n");
notconnected = 0;
}
if (not_sending() && tox_get_friend_connection_status(tox, num)) {
if (not_sending() && tox_friend_get_connection_status(tox, num, 0)) {
d = opendir(path);
if (d) {
@ -290,8 +320,7 @@ int main(int argc, char *argv[])
}
}
send_filesenders(tox);
tox_do(tox);
tox_iterate(tox);
c_sleep(1);
}

View File

@ -23,9 +23,11 @@
#endif
#include "group.h"
#include "../toxcore/util.h"
#include "../toxcore/logger.h"
#define GROUP_JBUF_SIZE 6
#define GROUP_JBUF_DEAD_SECONDS 4
typedef struct {
uint16_t sequnum;
@ -39,6 +41,7 @@ typedef struct {
uint32_t capacity;
uint16_t bottom;
uint16_t top;
uint64_t last_queued_time;
} Group_JitterBuffer;
static Group_JitterBuffer *create_queue(unsigned int capacity)
@ -90,11 +93,19 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk)
unsigned int num = sequnum % q->size;
if (!is_timeout(q->last_queued_time, GROUP_JBUF_DEAD_SECONDS)) {
if ((uint32_t)(sequnum - q->bottom) > (1 << 15)) {
/* Drop old packet. */
return -1;
}
}
if ((uint32_t)(sequnum - q->bottom) > q->size) {
clear_queue(q);
q->bottom = sequnum - q->capacity;
q->queue[num] = pk;
q->top = sequnum + 1;
q->last_queued_time = unix_time();
return 0;
}
@ -106,6 +117,7 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk)
if ((sequnum - q->bottom) >= (q->top - q->bottom))
q->top = sequnum + 1;
q->last_queued_time = unix_time();
return 0;
}

View File

@ -774,7 +774,7 @@ static int terminate_call ( MSISession *session, MSICall *call )
return 0;
}
static void handle_remote_connection_change(Messenger *messenger, int friend_num, uint8_t status, void *session_p)
static void handle_remote_connection_change(Messenger *messenger, uint32_t friend_num, uint8_t status, void *session_p)
{
(void)messenger;
MSISession *session = session_p;
@ -1101,7 +1101,8 @@ static int handle_recv_error ( MSISession *session, MSICall *call, MSIMessage *m
*
*
*/
static void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data, uint16_t length, void *object )
static void msi_handle_packet ( Messenger *messenger, uint32_t source, const uint8_t *data, uint16_t length,
void *object )
{
LOGGER_DEBUG("Got msi message");
/* Unused */

View File

@ -341,7 +341,7 @@ RTPMessage *msg_parse ( const uint8_t *data, int length )
/**
* Callback for networking core.
*/
int rtp_handle_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object )
int rtp_handle_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object )
{
RTPSession *session = object;
RTPMessage *msg;
@ -428,13 +428,14 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
if ( !msg ) return -1;
if ( -1 == send_custom_lossy_packet(messenger, session->dest, msg->data, msg->length) ) {
LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno));
int ret = send_custom_lossy_packet(messenger, session->dest, msg->data, msg->length);
if ( 0 != ret) {
LOGGER_WARNING("Failed to send full packet (len: %d)! error: %i", length, ret);
rtp_free_msg ( session, msg );
return rtp_ErrorSending;
}
/* Set sequ number */
session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1;
rtp_free_msg ( session, msg );
@ -469,7 +470,7 @@ RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num )
return NULL;
}
if ( -1 == custom_lossy_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, retu)) {
if ( -1 == m_callback_rtp_packet(messenger, friend_num, payload_type, rtp_handle_packet, retu)) {
LOGGER_ERROR("Error setting custom register handler for rtp session");
free(retu);
return NULL;
@ -514,7 +515,7 @@ void rtp_kill ( RTPSession *session, Messenger *messenger )
{
if ( !session ) return;
custom_lossy_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL);
m_callback_rtp_packet(messenger, session->dest, session->prefix, NULL, NULL);
free ( session->ext_header );
free ( session->csrc );

View File

@ -23,7 +23,7 @@
#include "config.h"
#endif /* HAVE_CONFIG_H */
#define __TOX_DEFINED__
#define TOX_DEFINED
typedef struct Messenger Tox;
#define _GNU_SOURCE /* implicit declaration warning */

View File

@ -37,8 +37,8 @@ typedef void ( *ToxAVCallback ) ( void *agent, int32_t call_idx, void *arg );
typedef void ( *ToxAvAudioCallback ) (void *agent, int32_t call_idx, const int16_t *PCM, uint16_t size, void *data);
typedef void ( *ToxAvVideoCallback ) (void *agent, int32_t call_idx, const vpx_image_t *img, void *data);
#ifndef __TOX_DEFINED__
#define __TOX_DEFINED__
#ifndef TOX_DEFINED
#define TOX_DEFINED
typedef struct Tox Tox;
#endif

View File

@ -78,8 +78,8 @@ int id_closest(const uint8_t *id, const uint8_t *id1, const uint8_t *id2)
for (i = 0; i < CLIENT_ID_SIZE; ++i) {
distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]);
distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]);
distance1 = id[i] ^ id1[i];
distance2 = id[i] ^ id2[i];
if (distance1 < distance2)
return 1;

View File

@ -1,7 +1,8 @@
lib_LTLIBRARIES += libtoxcore.la
libtoxcore_la_include_HEADERS = \
../toxcore/tox.h
../toxcore/tox.h \
../toxcore/tox_old.h
libtoxcore_la_includedir = $(includedir)/tox

File diff suppressed because it is too large Load Diff

View File

@ -33,12 +33,15 @@
#define MAX_NAME_LENGTH 128
/* TODO: this must depend on other variable. */
#define MAX_STATUSMESSAGE_LENGTH 1007
#define AVATAR_MAX_DATA_LENGTH 16384
#define AVATAR_HASH_LENGTH crypto_hash_sha256_BYTES
#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t))
enum {
MESSAGE_NORMAL,
MESSAGE_ACTION
};
/* NOTE: Packet ids below 17 must never be used. */
#define PACKET_ID_SHARE_RELAYS 17
#define PACKET_ID_ONLINE 24
@ -47,14 +50,8 @@
#define PACKET_ID_STATUSMESSAGE 49
#define PACKET_ID_USERSTATUS 50
#define PACKET_ID_TYPING 51
#define PACKET_ID_AVATAR_INFO_REQ 52
#define PACKET_ID_AVATAR_INFO 53
#define PACKET_ID_AVATAR_DATA_CONTROL 54
#define PACKET_ID_AVATAR_DATA_START 55
#define PACKET_ID_AVATAR_DATA_PUSH 56
#define PACKET_ID_RECEIPT 63
#define PACKET_ID_MESSAGE 64
#define PACKET_ID_ACTION 65
#define PACKET_ID_ACTION (PACKET_ID_MESSAGE + MESSAGE_ACTION) /* 65 */
#define PACKET_ID_MSI 69
#define PACKET_ID_FILE_SENDREQUEST 80
#define PACKET_ID_FILE_CONTROL 81
@ -71,13 +68,22 @@
/* All packets starting with a byte in this range can be used for anything. */
#define PACKET_ID_LOSSLESS_RANGE_START 160
#define PACKET_ID_LOSSLESS_RANGE_SIZE 32
#define PACKET_LOSSY_AV_RESERVED 8 /* Number of lossy packet types at start of range reserved for A/V. */
typedef struct {
uint8_t ipv6enabled;
uint8_t udp_disabled;
TCP_Proxy_Info proxy_info;
uint16_t port_range[2];
} Messenger_Options;
struct Receipts {
uint32_t packet_num;
uint32_t msg_id;
struct Receipts *next;
};
/* Status definitions. */
enum {
NOFRIEND,
@ -95,25 +101,23 @@ enum {
FAERR_NOMESSAGE = -2,
FAERR_OWNKEY = -3,
FAERR_ALREADYSENT = -4,
FAERR_UNKNOWN = -5,
FAERR_BADCHECKSUM = -6,
FAERR_SETNEWNOSPAM = -7,
FAERR_NOMEM = -8
};
/* Default start timeout in seconds between friend requests. */
#define FRIENDREQUEST_TIMEOUT 5;
/* Interval between the sending of tcp relay information */
#define FRIEND_SHARE_RELAYS_INTERVAL (5 * 60)
/* Must be < MAX_CRYPTO_DATA_SIZE */
#define AVATAR_DATA_MAX_CHUNK_SIZE (MAX_CRYPTO_DATA_SIZE-1)
/* Per-friend data limit for avatar data requests */
#define AVATAR_DATA_TRANSFER_LIMIT (10*AVATAR_MAX_DATA_LENGTH)
#define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */
enum {
CONNECTION_NONE,
CONNECTION_TCP,
CONNECTION_UDP
};
/* USERSTATUS -
* Represents userstatuses someone can have.
@ -127,56 +131,33 @@ typedef enum {
}
USERSTATUS;
/* AVATAR_FORMAT -
* Data formats for user avatar images
*/
typedef enum {
AVATAR_FORMAT_NONE = 0,
AVATAR_FORMAT_PNG
}
AVATAR_FORMAT;
/* AVATAR_DATACONTROL
* To control avatar data requests (PACKET_ID_AVATAR_DATA_CONTROL)
*/
typedef enum {
AVATAR_DATACONTROL_REQ,
AVATAR_DATACONTROL_ERROR
}
AVATAR_DATACONTROL;
typedef struct {
uint8_t started;
AVATAR_FORMAT format;
uint8_t hash[AVATAR_HASH_LENGTH];
uint32_t total_length;
uint32_t bytes_received;
uint8_t data[AVATAR_MAX_DATA_LENGTH];
}
AVATAR_RECEIVEDATA;
typedef struct {
/* Fields only used to limit the network usage from a given friend */
uint32_t bytes_sent; /* Total bytes send to this user */
uint64_t last_reset; /* Time the data counter was last reset */
}
AVATAR_SENDDATA;
#define FILE_ID_LENGTH 32
struct File_Transfers {
uint64_t size;
uint64_t transferred;
uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused by the other, 3 = transferring, 4 = broken, 5 = paused by us */
uint8_t status; /* 0 == no transfer, 1 = not accepted, 3 = transferring, 4 = broken, 5 = finished */
uint8_t paused; /* 0: not paused, 1 = paused by us, 2 = paused by other, 3 = paused by both. */
uint32_t last_packet_number; /* number of the last packet sent. */
uint64_t requested; /* total data requested by the request chunk callback */
unsigned int slots_allocated; /* number of slots allocated to this transfer. */
uint8_t id[FILE_ID_LENGTH];
};
enum {
FILESTATUS_NONE,
FILESTATUS_NOT_ACCEPTED,
FILESTATUS_PAUSED_BY_OTHER,
FILESTATUS_TRANSFERRING,
FILESTATUS_BROKEN,
FILESTATUS_PAUSED_BY_US,
FILESTATUS_TEMPORARY
//FILESTATUS_BROKEN,
FILESTATUS_FINISHED
};
enum {
FILE_PAUSE_NOT,
FILE_PAUSE_US,
FILE_PAUSE_OTHER,
FILE_PAUSE_BOTH
};
/* This cannot be bigger than 256 */
#define MAX_CONCURRENT_FILE_PIPES 256
@ -184,10 +165,15 @@ enum {
FILECONTROL_ACCEPT,
FILECONTROL_PAUSE,
FILECONTROL_KILL,
FILECONTROL_FINISHED,
FILECONTROL_RESUME_BROKEN
FILECONTROL_SEEK
};
enum {
FILEKIND_DATA,
FILEKIND_AVATAR
};
typedef struct Messenger Messenger;
typedef struct {
@ -201,36 +187,31 @@ typedef struct {
uint8_t name[MAX_NAME_LENGTH];
uint16_t name_length;
uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have.
uint8_t *statusmessage;
uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
uint16_t statusmessage_length;
uint8_t statusmessage_sent;
USERSTATUS userstatus;
uint8_t userstatus_sent;
uint8_t avatar_info_sent;
uint8_t user_istyping;
uint8_t user_istyping_sent;
uint8_t is_typing;
uint16_t info_size; // Length of the info.
uint32_t message_id; // a semi-unique id used in read receipts.
uint8_t receives_read_receipts; // shall we send read receipts to this person?
uint32_t friendrequest_nospam; // The nospam number used in the friend request.
uint64_t ping_lastrecv;//TODO remove
uint64_t share_relays_lastsent;
uint8_t last_connection_udp_tcp;
struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
unsigned int num_sending_files;
struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
AVATAR_SENDDATA avatar_send_data;
AVATAR_RECEIVEDATA *avatar_recv_data; // We are receiving avatar data from this friend.
struct {
int (*function)(Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object);
int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object);
void *object;
} lossy_packethandlers[PACKET_ID_LOSSY_RANGE_SIZE];
} lossy_rtp_packethandlers[PACKET_LOSSY_AV_RESERVED];
struct {
int (*function)(Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object);
void *object;
} lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE];
struct Receipts *receipts_start;
struct Receipts *receipts_end;
} Friend;
@ -255,11 +236,6 @@ struct Messenger {
USERSTATUS userstatus;
AVATAR_FORMAT avatar_format;
uint8_t *avatar_data;
uint32_t avatar_data_length;
uint8_t avatar_hash[AVATAR_HASH_LENGTH];
Friend *friendlist;
uint32_t numfriends;
@ -271,45 +247,49 @@ struct Messenger {
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
void (*friend_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, void *);
void (*friend_message)(struct Messenger *m, uint32_t, unsigned int, const uint8_t *, size_t, void *);
void *friend_message_userdata;
void (*friend_action)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, void *);
void *friend_action_userdata;
void (*friend_namechange)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, void *);
void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
void *friend_namechange_userdata;
void (*friend_statusmessagechange)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, void *);
void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
void *friend_statusmessagechange_userdata;
void (*friend_userstatuschange)(struct Messenger *m, int32_t, uint8_t, void *);
void (*friend_userstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
void *friend_userstatuschange_userdata;
void (*friend_typingchange)(struct Messenger *m, int32_t, uint8_t, void *);
void (*friend_typingchange)(struct Messenger *m, uint32_t, _Bool, void *);
void *friend_typingchange_userdata;
void (*read_receipt)(struct Messenger *m, int32_t, uint32_t, void *);
void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *);
void *read_receipt_userdata;
void (*friend_statuschange)(struct Messenger *m, int32_t, uint8_t, void *);
void *friend_statuschange_userdata;
void (*friend_connectionstatuschange)(struct Messenger *m, int32_t, uint8_t, void *);
void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
void *friend_connectionstatuschange_userdata;
void (*friend_connectionstatuschange_internal)(struct Messenger *m, int32_t, uint8_t, void *);
void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *);
void *friend_connectionstatuschange_internal_userdata;
void *avatar_info_recv_userdata;
void (*avatar_info_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, void *);
void *avatar_data_recv_userdata;
void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *);
void *group_chat_object; /* Set by new_groupchats()*/
void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, uint16_t);
void (*group_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t);
void (*group_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t);
void (*group_message)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t);
void (*file_sendrequest)(struct Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *);
void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t,
void *);
void *file_sendrequest_userdata;
void (*file_filecontrol)(struct Messenger *m, int32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, void *);
void (*file_filecontrol)(struct Messenger *m, uint32_t, uint32_t, unsigned int, void *);
void *file_filecontrol_userdata;
void (*file_filedata)(struct Messenger *m, int32_t, uint8_t, const uint8_t *, uint16_t length, void *);
void (*file_filedata)(struct Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
void *file_filedata_userdata;
void (*file_reqchunk)(struct Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *);
void *file_reqchunk_userdata;
void (*msi_packet)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, void *);
void (*msi_packet)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
void *msi_packet_userdata;
void (*lossy_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
void *lossy_packethandler_userdata;
void (*lossless_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
void *lossless_packethandler_userdata;
void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
void *core_connection_change_userdata;
unsigned int last_connection_status;
Messenger_Options options;
};
@ -329,7 +309,6 @@ void getaddress(const Messenger *m, uint8_t *address);
* return -2 if no message (message length must be >= 1 byte).
* return -3 if user's own key.
* return -4 if friend request already sent or already a friend.
* return -5 for unknown error.
* return -6 if bad checksum in address.
* return -7 if the friend was already there but the nospam was different.
* (the nospam for that friend was set to the new one).
@ -340,7 +319,10 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
/* Add a friend without sending a friendrequest.
* return the friend number if success.
* return -1 if failure.
* return -3 if user's own key.
* return -4 if friend request already sent or already a friend.
* return -6 if bad checksum in address.
* return -8 if increasing the friend list size fails.
*/
int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk);
@ -371,8 +353,9 @@ int m_delfriend(Messenger *m, int32_t friendnumber);
/* Checks friend's connecting status.
*
* return 1 if friend is connected to us (Online).
* return 0 if friend is not connected to us (Offline).
* return CONNECTION_UDP (2) if friend is directly connected to us (Online UDP).
* return CONNECTION_TCP (1) if friend is connected to us (Online TCP).
* return CONNECTION_NONE (0) if friend is not connected to us (Offline).
* return -1 on failure.
*/
int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber);
@ -384,33 +367,20 @@ int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber);
*/
int m_friend_exists(const Messenger *m, int32_t friendnumber);
/* Send a text chat message to an online friend.
/* Send a message of type to an online friend.
*
* return the message id if packet was successfully put into the send queue.
* return 0 if it was not.
* return -1 if friend not valid.
* return -2 if too large.
* return -3 if friend not online.
* return -4 if send failed (because queue is full).
* return -5 if bad type.
* return 0 if success.
*
* You will want to retain the return value, it will be passed to your read_receipt callback
* if one is received.
* m_sendmessage_withid will send a message with the id of your choosing,
* however we can generate an id for you by calling plain m_sendmessage.
* the value in message_id will be passed to your read_receipt callback when the other receives the message.
*/
uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length);
uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message,
uint32_t length);
int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
uint32_t *message_id);
/* Send an action to an online friend.
*
* return the message id if packet was successfully put into the send queue.
* return 0 if it was not.
*
* You will want to retain the return value, it will be passed to your read_receipt callback
* if one is received.
* m_sendaction_withid will send an action message with the id of your choosing,
* however we can generate an id for you by calling plain m_sendaction.
*/
uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length);
uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action,
uint32_t length);
/* Set the name and name_length of a friend.
* name must be a string of maximum MAX_NAME_LENGTH length.
@ -479,7 +449,7 @@ int m_get_self_statusmessage_size(const Messenger *m);
* retruns -1 on failure.
*/
int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen);
int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf, uint32_t maxlen);
int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf);
/* return one of USERSTATUS values.
* Values unknown to your application should be represented as USERSTATUS_NONE.
@ -490,113 +460,6 @@ uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
uint8_t m_get_self_userstatus(const Messenger *m);
/* Set the user avatar image data.
* This should be made before connecting, so we will not announce that the user have no avatar
* before setting and announcing a new one, forcing the peers to re-download it.
*
* Notice that the library treats the image as raw data and does not interpret it by any way.
*
* Arguments:
* format - Avatar image format or NONE for user with no avatar (see AVATAR_FORMAT);
* data - pointer to the avatar data (may be NULL it the format is NONE);
* length - length of image data. Must be <= MAX_AVATAR_DATA_LENGTH.
*
* returns 0 on success
* returns -1 on failure.
*/
int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length);
/* Unsets the user avatar.
returns 0 on success (currently always returns 0) */
int m_unset_avatar(Messenger *m);
/* Get avatar data from the current user.
* Copies the current user avatar data to the destination buffer and sets the image format
* accordingly.
*
* If the avatar format is NONE, the buffer 'buf' isleft uninitialized, 'hash' is zeroed, and
* 'length' is set to zero.
*
* If any of the pointers format, buf, length, and hash are NULL, that particular field will be ignored.
*
* Arguments:
* format - destination pointer to the avatar image format (see AVATAR_FORMAT);
* buf - destination buffer to the image data. Must have at least 'maxlen' bytes;
* length - destination pointer to the image data length;
* maxlen - length of the destination buffer 'buf';
* hash - destination pointer to the avatar hash (it must be exactly AVATAR_HASH_LENGTH bytes long).
*
* returns 0 on success;
* returns -1 on failure.
*
*/
int m_get_self_avatar(const Messenger *m, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen,
uint8_t *hash);
/* Generates a cryptographic hash of the given data.
* This function may be used by clients for any purpose, but is provided primarily for
* validating cached avatars.
* This function is a wrapper to internal message-digest functions.
*
* Arguments:
* hash - destination buffer for the hash data, it must be exactly crypto_hash_sha256_BYTES bytes long.
* data - data to be hashed;
* datalen - length of the data;
*
* returns 0 on success
* returns -1 on failure.
*/
int m_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen);
/* Generates a cryptographic hash of the given avatar data.
* This function is a wrapper to m_hash and specifically provided
* to generate hashes from user avatars that may be memcmp()ed with the values returned by the
* other avatar functions. It is specially important to validate cached avatars.
*
* Arguments:
* hash - destination buffer for the hash data, it must be exactly AVATAR_HASH_LENGTH bytes long.
* data - avatar image data;
* datalen - length of the avatar image data; it must be <= MAX_AVATAR_DATA_LENGTH.
*
* returns 0 on success
* returns -1 on failure.
*/
int m_avatar_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen);
/* Request avatar information from a friend.
* Asks a friend to provide their avatar information (image format and hash). The friend may
* or may not answer this request and, if answered, the information will be provided through
* the callback 'avatar_info'.
*
* returns 0 on success
* returns -1 on failure.
*/
int m_request_avatar_info(const Messenger *m, const int32_t friendnumber);
/* Send an unrequested avatar information to a friend.
* Sends our avatar format and hash to a friend; he/she can use this information to validate
* an avatar from the cache and may (or not) reply with an avatar data request.
*
* Notice: it is NOT necessary to send these notification after changing the avatar or
* connecting. The library already does this.
*
* returns 0 on success
* returns -1 on failure.
*/
int m_send_avatar_info(const Messenger *m, const int32_t friendnumber);
/* Request the avatar data from a friend.
* Ask a friend to send their avatar data. The friend may or may not answer this request and,
* if answered, the information will be provided in callback 'avatar_data'.
*
* returns 0 on sucess
* returns -1 on failure.
*/
int m_request_avatar_data(const Messenger *m, const int32_t friendnumber);
/* returns timestamp of last time friendnumber was seen online, or 0 if never seen.
* returns -1 on error.
*/
@ -615,58 +478,48 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing);
* returns 0 if friend is not typing.
* returns 1 if friend is typing.
*/
uint8_t m_get_istyping(const Messenger *m, int32_t friendnumber);
/* Sets whether we send read receipts for friendnumber.
* This function is not lazy, and it will fail if yesno is not (0 or 1).
*/
void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno);
int m_get_istyping(const Messenger *m, int32_t friendnumber);
/* Set the function that will be executed when a friend request is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)
* Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
*/
void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, uint16_t,
void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
void *), void *userdata);
/* Set the function that will be executed when a message from a friend is received.
* Function format is: function(int32_t friendnumber, uint8_t * message, uint32_t length)
* Function format is: function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length)
*/
void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *),
void *userdata);
/* Set the function that will be executed when an action from a friend is received.
* Function format is: function(int32_t friendnumber, uint8_t * action, uint32_t length)
*/
void m_callback_action(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *),
void *userdata);
void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
size_t, void *), void *userdata);
/* Set the callback for name changes.
* Function(int32_t friendnumber, uint8_t *newname, uint16_t length)
* Function(uint32_t friendnumber, uint8_t *newname, size_t length)
* You are not responsible for freeing newname.
*/
void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *),
void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *),
void *userdata);
/* Set the callback for status message changes.
* Function(int32_t friendnumber, uint8_t *newstatus, uint16_t length)
* Function(uint32_t friendnumber, uint8_t *newstatus, size_t length)
*
* You are not responsible for freeing newstatus
*/
void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *),
void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *),
void *userdata);
/* Set the callback for status type changes.
* Function(int32_t friendnumber, USERSTATUS kind)
* Function(uint32_t friendnumber, USERSTATUS kind)
*/
void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *), void *userdata);
void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *),
void *userdata);
/* Set the callback for typing changes.
* Function(int32_t friendnumber, uint8_t is_typing)
* Function(uint32_t friendnumber, uint8_t is_typing)
*/
void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, int32_t, uint8_t, void *), void *userdata);
void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata);
/* Set the callback for read receipts.
* Function(int32_t friendnumber, uint32_t receipt)
* Function(uint32_t friendnumber, uint32_t receipt)
*
* If you are keeping a record of returns from m_sendmessage,
* receipt might be one of those values, meaning the message
@ -674,10 +527,10 @@ void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, int32_t
* Since core doesn't track ids for you, receipt may not correspond to any message.
* In that case, you should discard it.
*/
void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int32_t, uint32_t, void *), void *userdata);
void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *), void *userdata);
/* Set the callback for connection status changes.
* function(int32_t friendnumber, uint8_t status)
* function(uint32_t friendnumber, uint8_t status)
*
* Status:
* 0 -- friend went offline after being previously online.
@ -687,62 +540,25 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int32_
* being previously online" part.
* It's assumed that when adding friends, their connection status is offline.
*/
void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *),
void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *),
void *userdata);
/* Same as previous but for internal A/V core usage only */
void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *),
void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
void *userdata);
/* Set the callback function for avatar information.
* This callback will be called when avatar information are received from friends. These events
* can arrive at anytime, but are usually received uppon connection and in reply of avatar
* information requests.
*
* Function format is:
* function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata)
*
* where 'format' is the avatar image format (see AVATAR_FORMAT) and 'hash' is the hash of
* the avatar data for caching purposes and it is exactly AVATAR_HASH_LENGTH long. If the
* image format is NONE, the hash is zeroed.
*
/* Set the callback for typing changes.
* Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP))
*/
void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, void *),
void *userdata);
/* Set the callback function for avatar data.
* This callback will be called when the complete avatar data was correctly received from a
* friend. This only happens in reply of a avatar data request (see tox_request_avatar_data);
*
* Function format is:
* function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata)
*
* where 'format' is the avatar image format (see AVATAR_FORMAT); 'hash' is the
* locally-calculated cryptographic hash of the avatar data and it is exactly
* AVATAR_HASH_LENGTH long; 'data' is the avatar image data and 'datalen' is the length
* of such data.
*
* If format is NONE, 'data' is NULL, 'datalen' is zero, and the hash is zeroed. The hash is
* always validated locally with the function tox_avatar_hash and ensured to match the image
* data, so this value can be safely used to compare with cached avatars.
*
* WARNING: users MUST treat all avatar image data received from another peer as untrusted and
* potentially malicious. The library only ensures that the data which arrived is the same the
* other user sent, and does not interpret or validate any image data.
*/
void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *,
uint32_t, void *), void *userdata);
void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata);
/**********GROUP CHATS************/
/* Set the callback for group invites.
*
* Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length)
* Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length)
*/
void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t));
void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t));
/* Send a group invite packet.
*
@ -756,58 +572,97 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin
/* Set the callback for file send requests.
*
* Function(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
* Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
*/
void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *,
uint16_t, void *), void *userdata);
void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
const uint8_t *, size_t, void *), void *userdata);
/* Set the callback for file control requests.
*
* Function(Tox *tox, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
* Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
*
*/
void callback_file_control(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t, uint8_t,
const uint8_t *, uint16_t, void *), void *userdata);
void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *),
void *userdata);
/* Set the callback for file data.
*
* Function(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
* Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, uint8_t *data, size_t length, void *userdata)
*
*/
void callback_file_data(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, uint16_t length,
void *), void *userdata);
void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
size_t, void *), void *userdata);
/* Send a file send request.
* Maximum filename length is 255 bytes.
* return 1 on success
* return 0 on failure
/* Set the callback for file request chunk.
*
* Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
*
*/
int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
const uint8_t *filename, uint16_t filename_length);
void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *),
void *userdata);
/* Copy the file transfer file id to file_id
*
* return 0 on success.
* return -1 if friend not valid.
* return -2 if filenumber not valid
*/
int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id);
/* Send a file send request.
* Maximum filename length is 255 bytes.
* return file number on success
* return -1 on failure
* return -1 if friend not found.
* return -2 if filename length invalid.
* return -3 if no more file sending slots left.
* return -4 if could not send packet (friend offline).
*
*/
int new_filesender(const Messenger *m, int32_t friendnumber, uint64_t filesize, const uint8_t *filename,
uint16_t filename_length);
long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length);
/* Send a file control request.
* send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file.
*
* return 1 on success
* return 0 on failure
* return 0 on success
* return -1 if friend not valid.
* return -2 if friend not online.
* return -3 if file number invalid.
* return -4 if file control is bad.
* return -5 if file already paused.
* return -6 if resume file failed because it was only paused by the other.
* return -7 if resume file failed because it wasn't paused.
* return -8 if packet failed to send.
*/
int file_control(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
const uint8_t *data, uint16_t length);
int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control);
/* Send a seek file control request.
*
* return 0 on success
* return -1 if friend not valid.
* return -2 if friend not online.
* return -3 if file number invalid.
* return -4 if not receiving file.
* return -5 if file status wrong.
* return -6 if position bad.
* return -8 if packet failed to send.
*/
int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position);
/* Send file data.
*
* return 1 on success
* return 0 on failure
* return 0 on success
* return -1 if friend not valid.
* return -2 if friend not online.
* return -3 if filenumber invalid.
* return -4 if file transfer not transferring.
* return -5 if bad data size.
* return -6 if packet queue full.
* return -7 if wrong position.
*/
int file_data(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length);
int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
uint16_t length);
/* Give the number of bytes left to be sent/received.
*
@ -822,9 +677,9 @@ uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t fi
/* Set the callback for msi packets.
*
* Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
* Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
*/
void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *),
void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t, void *),
void *userdata);
/* Send an msi packet.
@ -834,20 +689,29 @@ void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, int32_t,
*/
int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
/**********************************************/
/* Set handlers for custom lossy packets (RTP packets for example.)
/* Set handlers for lossy rtp packets.
*
* return -1 on failure.
* return 0 on success.
*/
int custom_lossy_packet_registerhandler(Messenger *m, int32_t friendnumber, uint8_t byte,
int (*packet_handler_callback)(Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object),
void *object);
int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m,
uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object);
/**********************************************/
/* Set handlers for custom lossy packets.
*
*/
void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object);
/* High level function to send custom lossy packets.
*
* return -1 on failure.
* return -1 if friend invalid.
* return -2 if length wrong.
* return -3 if first byte invalid.
* return -4 if friend offline.
* return -5 if packet failed to send because of other error.
* return 0 on success.
*/
int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
@ -855,28 +719,36 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin
/* Set handlers for custom lossless packets.
*
* byte must be in PACKET_ID_LOSSLESS_RANGE_START PACKET_ID_LOSSLESS_RANGE_SIZE range.
*
* return -1 on failure.
* return 0 on success.
*/
int custom_lossless_packet_registerhandler(Messenger *m, int32_t friendnumber, uint8_t byte,
int (*packet_handler_callback)(Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object),
void *object);
void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object);
/* High level function to send custom lossless packets.
*
* return -1 on failure.
* return -1 if friend invalid.
* return -2 if length wrong.
* return -3 if first byte invalid.
* return -4 if friend offline.
* return -5 if packet failed to send because of other error.
* return 0 on success.
*/
int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
/**********************************************/
enum {
MESSENGER_ERROR_NONE,
MESSENGER_ERROR_PORT,
MESSENGER_ERROR_OTHER
};
/* Run this at startup.
* return allocated instance of Messenger on success.
* return 0 if there are problems.
*
* if error is not NULL it will be set to one of the values in the enum above.
*/
Messenger *new_messenger(Messenger_Options *options);
Messenger *new_messenger(Messenger_Options *options, unsigned int *error);
/* Run this before closing shop
* Free all datastructures.
@ -891,7 +763,7 @@ void do_messenger(Messenger *m);
*
* returns time (in ms) before the next do_messenger() needs to be run on success.
*/
uint32_t messenger_run_interval(Messenger *m);
uint32_t messenger_run_interval(const Messenger *m);
/* SAVING AND LOADING FUNCTIONS: */
@ -917,6 +789,6 @@ uint32_t get_num_online_friends(const Messenger *m);
* Otherwise, returns the number of elements copied.
* If the array was too small, the contents
* of out_list will be truncated to list_size. */
uint32_t copy_friendlist(const Messenger *m, int32_t *out_list, uint32_t list_size);
uint32_t copy_friendlist(const Messenger *m, uint32_t *out_list, uint32_t list_size);
#endif

View File

@ -122,7 +122,7 @@ void new_nonce(uint8_t *nonce);
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
#define CRYPTO_PACKET_FAKEID 156
#define CRYPTO_PACKET_DHTPK 156
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
/* Create a request to peer.

View File

@ -42,7 +42,7 @@ uint32_t get_nospam(const Friend_Requests *fr)
/* Set the function that will be executed when a friend request is received. */
void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, uint16_t,
void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
void *), void *object, void *userdata)
{
fr->handle_friendrequest = function;

View File

@ -30,7 +30,7 @@
typedef struct {
uint32_t nospam;
void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, uint16_t, void *);
void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *);
uint8_t handle_friendrequest_isset;
void *handle_friendrequest_object;
void *handle_friendrequest_userdata;
@ -59,9 +59,9 @@ uint32_t get_nospam(const Friend_Requests *fr);
int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);
/* Set the function that will be executed when a friend request for us is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length, void * userdata)
* Function format is function(uint8_t * public_key, uint8_t * data, size_t length, void * userdata)
*/
void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, uint16_t,
void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
void *), void *object, void *userdata);
/* Set the function used to check if a friend request should be displayed to the user or not.

View File

@ -518,7 +518,7 @@ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index)
static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len)
{
if (nick_len > MAX_NAME_LENGTH || nick_len == 0)
if (nick_len > MAX_NAME_LENGTH)
return -1;
Group_c *g = get_group_c(g_c, groupnumber);
@ -528,10 +528,12 @@ static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint
/* same name as already stored? */
if (g->group[peer_index].nick_len == nick_len)
if (!memcmp(g->group[peer_index].nick, nick, nick_len))
if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len))
return 0;
if (nick_len)
memcpy(g->group[peer_index].nick, nick, nick_len);
g->group[peer_index].nick_len = nick_len;
if (g_c->peer_namelistchange)
@ -1234,7 +1236,7 @@ int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uin
return max_length;
}
static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length)
{
Group_Chats *g_c = m->group_chat_object;

View File

@ -722,7 +722,7 @@ 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]->time = 0;
send_array->buffer[num]->sent = 0;
}
++data;
@ -809,6 +809,43 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3
return send_data_packet(c, crypt_connection_id, packet, sizeof(packet));
}
static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
{
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
if (conn == 0)
return -1;
/* If last packet send failed, try to send packet again.
If sending it fails we won't be able to send the new packet. */
if (conn->maximum_speed_reached) {
Packet_Data *dt = NULL;
uint32_t packet_num = conn->send_array.buffer_end - 1;
int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
uint8_t send_failed = 0;
if (ret == 1) {
if (!dt->sent) {
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;
}
}
}
if (!send_failed) {
conn->maximum_speed_reached = 0;
} else {
return -1;
}
}
return 0;
}
/* return -1 if data could not be put in packet queue.
* return positive packet number if data was put into the queue.
*/
@ -823,39 +860,16 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
if (conn == 0)
return -1;
uint64_t temp_time = current_time_monotonic();
/* If last packet send failed, try to send packet again.
If sending it fails we won't be able to send the new packet. */
if (conn->maximum_speed_reached) {
Packet_Data *dt = NULL;
uint32_t packet_num = conn->send_array.buffer_end - 1;
int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
reset_max_speed_reached(c, crypt_connection_id);
uint8_t send_failed = 0;
if (ret == 1) {
if (!dt->time) {
if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
dt->length) != 0) {
if (congestion_control) {
if (conn->maximum_speed_reached && congestion_control) {
return -1;
} else {
send_failed = 1;
}
} else {
dt->time = temp_time;
}
}
}
if (!send_failed) {
conn->maximum_speed_reached = 0;
}
}
Packet_Data dt;
dt.time = 0;
dt.sent = 0;
dt.length = length;
memcpy(dt.data, data, length);
pthread_mutex_lock(&conn->mutex);
@ -873,7 +887,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->time = temp_time;
dt1->sent = 1;
} else {
conn->maximum_speed_reached = 1;
LOGGER_ERROR("send_data_packet failed\n");
@ -983,15 +997,15 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16
continue;
}
if (dt->time != 0) {
if (dt->sent) {
continue;
}
dt->time = current_time_monotonic();
if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
dt->length) == 0)
dt->length) == 0) {
dt->sent = 1;
++num_sent;
}
if (num_sent >= max_num)
break;
@ -1189,7 +1203,6 @@ static int handle_data_packet_helper(const Net_Crypto *c, int crypt_connection_i
set_buffer_end(&conn->recv_array, num);
} else if (real_data[0] >= CRYPTO_RESERVED_PACKETS && real_data[0] < PACKET_ID_LOSSY_RANGE_START) {
Packet_Data dt;
dt.time = current_time_monotonic();
dt.length = real_length;
memcpy(dt.data, real_data, real_length);
@ -2529,7 +2542,7 @@ static void send_crypto_packets(Net_Crypto *c)
if (conn->last_packets_left_set == 0) {
conn->last_packets_left_set = temp_time;
conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
} else if (((1000.0 / conn->packet_send_rate) + conn->last_packets_left_set) < temp_time) {
} else if (((uint64_t)((1000.0 / conn->packet_send_rate) + 0.5) + conn->last_packets_left_set) < temp_time) {
uint32_t num_packets = conn->packet_send_rate * ((double)(temp_time - conn->last_packets_left_set) / 1000.0) + 0.5;
if (conn->packets_left > num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH) {
@ -2575,6 +2588,13 @@ static void send_crypto_packets(Net_Crypto *c)
}
}
/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
* Return 0 if it wasn't reached.
*/
_Bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)
{
return reset_max_speed_reached(c, crypt_connection_id) != 0;
}
/* returns the number of packet slots left in the sendbuffer.
* return 0 if failure.
@ -2586,7 +2606,13 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
if (conn == 0)
return 0;
uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array);
if (conn->packets_left < max_packets) {
return conn->packets_left;
} else {
return max_packets;
}
}
/* Sends a lossless cryptopacket.

View File

@ -89,7 +89,7 @@
#define CONGESTION_QUEUE_ARRAY_SIZE 24
typedef struct {
uint64_t time;
_Bool sent;
uint16_t length;
uint8_t data[MAX_CRYPTO_DATA_SIZE];
} Packet_Data;
@ -317,6 +317,11 @@ int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(
*/
uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id);
/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
* Return 0 if it wasn't reached.
*/
_Bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
/* Sends a lossless cryptopacket.
*
* return -1 if data could not be put in packet queue.

View File

@ -466,6 +466,14 @@ static void at_shutdown(void)
}
*/
/* Initialize networking.
* Added for reverse compatibility with old new_networking calls.
*/
Networking_Core *new_networking(IP ip, uint16_t port)
{
return new_networking_ex(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 0);
}
/* Initialize networking.
* Bind to ip and port.
* ip must be in network order EX: 127.0.0.1 = (7F000001).
@ -473,9 +481,31 @@ static void at_shutdown(void)
*
* return Networking_Core object if no problems
* return NULL if there are problems.
*
* If error is non NULL it is set to 0 if no issues, 1 if bind failed, 2 if other.
*/
Networking_Core *new_networking(IP ip, uint16_t port)
Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
{
/* If both from and to are 0, use default port range
* If one is 0 and the other is non-0, use the non-0 value as only port
* If from > to, swap
*/
if (port_from == 0 && port_to == 0) {
port_from = TOX_PORTRANGE_FROM;
port_to = TOX_PORTRANGE_TO;
} else if (port_from == 0 && port_to != 0) {
port_from = port_to;
} else if (port_from != 0 && port_to == 0) {
port_to = port_from;
} else if (port_from > port_to) {
uint16_t temp = port_from;
port_from = port_to;
port_to = temp;
}
if (error)
*error = 2;
/* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
if (ip.family != AF_INET && ip.family != AF_INET6) {
#ifdef DEBUG
@ -600,11 +630,11 @@ Networking_Core *new_networking(IP ip, uint16_t port)
* some clients might not test return of tox_new(), blindly assuming that
* it worked ok (which it did previously without a successful bind)
*/
uint16_t port_to_try = port;
uint16_t port_to_try = port_from;
*portptr = htons(port_to_try);
int tries;
for (tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++) {
for (tries = port_from; tries <= port_to; tries++) {
int res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
if (!res) {
@ -618,22 +648,28 @@ Networking_Core *new_networking(IP ip, uint16_t port)
if (tries > 0)
errno = 0;
if (error)
*error = 0;
return temp;
}
port_to_try++;
if (port_to_try > TOX_PORTRANGE_TO)
port_to_try = TOX_PORTRANGE_FROM;
if (port_to_try > port_to)
port_to_try = port_from;
*portptr = htons(port_to_try);
}
#ifdef DEBUG
fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
strerror(errno), ip_ntoa(&ip), port);
#endif
LOGGER_ERROR("Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno),
ip_ntoa(&ip), port_from, port_to);
kill_networking(temp);
if (error)
*error = 1;
return NULL;
}

View File

@ -362,8 +362,11 @@ void networking_poll(Networking_Core *net);
*
* return Networking_Core object if no problems
* return NULL if there are problems.
*
* If error is non NULL it is set to 0 if no issues, 1 if bind failed, 2 if other.
*/
Networking_Core *new_networking(IP ip, uint16_t port);
Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error);
/* Function to cleanup networking stuff (doesn't do much right now). */
void kill_networking(Networking_Core *net);

View File

@ -858,7 +858,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
onion_c->friends_list[friend_num].dht_public_key, temp, sizeof(temp), CRYPTO_PACKET_FAKEID);
onion_c->friends_list[friend_num].dht_public_key, temp, sizeof(temp), CRYPTO_PACKET_DHTPK);
if (len == -1)
return -1;
@ -1351,78 +1351,10 @@ static void do_announce(Onion_Client *onion_c)
}
}
void do_onion_client(Onion_Client *onion_c)
{
unsigned int i;
if (onion_c->last_run == unix_time())
return;
populate_path_nodes(onion_c);
do_announce(onion_c);
if (onion_isconnected(onion_c)) {
for (i = 0; i < onion_c->num_friends; ++i) {
do_friend(onion_c, i);
}
} else {
populate_path_nodes_tcp(onion_c);
}
onion_c->last_run = unix_time();
}
Onion_Client *new_onion_client(Net_Crypto *c)
{
if (c == NULL)
return NULL;
Onion_Client *onion_c = calloc(1, sizeof(Onion_Client));
if (onion_c == NULL)
return NULL;
if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
free(onion_c);
return NULL;
}
onion_c->dht = c->dht;
onion_c->net = c->dht->net;
onion_c->c = c;
new_symmetric_key(onion_c->secret_symmetric_key);
crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_FAKEID, &handle_dht_dhtpk, onion_c);
tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c);
return onion_c;
}
void kill_onion_client(Onion_Client *onion_c)
{
if (onion_c == NULL)
return;
ping_array_free_all(&onion_c->announce_ping_array);
realloc_onion_friends(onion_c, 0);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_FAKEID, NULL, NULL);
tcp_onion_response_handler(onion_c->c, NULL, NULL);
memset(onion_c, 0, sizeof(Onion_Client));
free(onion_c);
}
/* return 0 if we are not connected to the network.
* return 1 if we are.
*/
int onion_isconnected(const Onion_Client *onion_c)
static int onion_isconnected(const Onion_Client *onion_c)
{
unsigned int i, num = 0, announced = 0;
@ -1457,3 +1389,102 @@ int onion_isconnected(const Onion_Client *onion_c)
return 0;
}
#define ONION_CONNECTION_SECONDS 2
/* return 0 if we are not connected to the network.
* return 1 if we are connected with TCP only.
* return 2 if we are also connected with UDP.
*/
unsigned int onion_connection_status(const Onion_Client *onion_c)
{
if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) {
if (onion_c->UDP_connected) {
return 2;
} else {
return 1;
}
}
return 0;
}
void do_onion_client(Onion_Client *onion_c)
{
unsigned int i;
if (onion_c->last_run == unix_time())
return;
populate_path_nodes(onion_c);
do_announce(onion_c);
if (onion_isconnected(onion_c)) {
if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) {
++onion_c->onion_connected;
}
onion_c->UDP_connected = DHT_non_lan_connected(onion_c->dht);
} else {
populate_path_nodes_tcp(onion_c);
if (onion_c->onion_connected != 0) {
--onion_c->onion_connected;
}
}
if (onion_connection_status(onion_c)) {
for (i = 0; i < onion_c->num_friends; ++i) {
do_friend(onion_c, i);
}
}
onion_c->last_run = unix_time();
}
Onion_Client *new_onion_client(Net_Crypto *c)
{
if (c == NULL)
return NULL;
Onion_Client *onion_c = calloc(1, sizeof(Onion_Client));
if (onion_c == NULL)
return NULL;
if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
free(onion_c);
return NULL;
}
onion_c->dht = c->dht;
onion_c->net = c->dht->net;
onion_c->c = c;
new_symmetric_key(onion_c->secret_symmetric_key);
crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c);
return onion_c;
}
void kill_onion_client(Onion_Client *onion_c)
{
if (onion_c == NULL)
return;
ping_array_free_all(&onion_c->announce_ping_array);
realloc_onion_friends(onion_c, 0);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, NULL, NULL);
tcp_onion_response_handler(onion_c->c, NULL, NULL);
memset(onion_c, 0, sizeof(Onion_Client));
free(onion_c);
}

View File

@ -57,7 +57,7 @@
/* Onion data packet ids. */
#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ
#define ONION_DATA_DHTPK CRYPTO_PACKET_FAKEID
#define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK
typedef struct {
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
@ -157,6 +157,9 @@ typedef struct {
} Onion_Data_Handlers[256];
uint64_t last_packet_recv;
unsigned int onion_connected;
_Bool UDP_connected;
} Onion_Client;
@ -278,8 +281,9 @@ void kill_onion_client(Onion_Client *onion_c);
/* return 0 if we are not connected to the network.
* return 1 if we are.
* return 1 if we are connected with TCP only.
* return 2 if we are also connected with UDP.
*/
int onion_isconnected(const Onion_Client *onion_c);
unsigned int onion_connection_status(const Onion_Client *onion_c);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

173
toxcore/tox_old.h Normal file
View File

@ -0,0 +1,173 @@
/**********GROUP CHAT FUNCTIONS ************/
/* Group chat types for tox_callback_group_invite function.
*
* TOX_GROUPCHAT_TYPE_TEXT groupchats must be accepted with the tox_join_groupchat() function.
* The function to accept TOX_GROUPCHAT_TYPE_AV is in toxav.
*/
enum {
TOX_GROUPCHAT_TYPE_TEXT,
TOX_GROUPCHAT_TYPE_AV
};
/* Set the callback for group invites.
*
* Function(Tox *tox, int32_t friendnumber, uint8_t type, const uint8_t *data, uint16_t length, void *userdata)
*
* data of length is what needs to be passed to join_groupchat().
*
* for what type means see the enum right above this comment.
*/
void tox_callback_group_invite(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, const uint8_t *, uint16_t,
void *), void *userdata);
/* Set the callback for group messages.
*
* Function(Tox *tox, int groupnumber, int peernumber, const uint8_t * message, uint16_t length, void *userdata)
*/
void tox_callback_group_message(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *),
void *userdata);
/* Set the callback for group actions.
*
* Function(Tox *tox, int groupnumber, int peernumber, const uint8_t * action, uint16_t length, void *userdata)
*/
void tox_callback_group_action(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *),
void *userdata);
/* Set callback function for title changes.
*
* Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata)
* if peernumber == -1, then author is unknown (e.g. initial joining the group)
*/
void tox_callback_group_title(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint8_t,
void *), void *userdata);
/* Set callback function for peer name list changes.
*
* It gets called every time the name list changes(new peer/name, deleted peer)
* Function(Tox *tox, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
*/
typedef enum {
TOX_CHAT_CHANGE_PEER_ADD,
TOX_CHAT_CHANGE_PEER_DEL,
TOX_CHAT_CHANGE_PEER_NAME,
} TOX_CHAT_CHANGE;
void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *),
void *userdata);
/* Creates a new groupchat and puts it in the chats array.
*
* return group number on success.
* return -1 on failure.
*/
int tox_add_groupchat(Tox *tox);
/* Delete a groupchat from the chats array.
*
* return 0 on success.
* return -1 if failure.
*/
int tox_del_groupchat(Tox *tox, int groupnumber);
/* Copy the name of peernumber who is in groupnumber to name.
* name must be at least TOX_MAX_NAME_LENGTH long.
*
* return length of name if success
* return -1 if failure
*/
int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name);
/* Copy the public key of peernumber who is in groupnumber to public_key.
* public_key must be TOX_PUBLIC_KEY_SIZE long.
*
* returns 0 on success
* returns -1 on failure
*/
int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key);
/* invite friendnumber to groupnumber
* return 0 on success
* return -1 on failure
*/
int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber);
/* Join a group (you need to have been invited first.) using data of length obtained
* in the group invite callback.
*
* returns group number on success
* returns -1 on failure.
*/
int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length);
/* send a group message
* return 0 on success
* return -1 on failure
*/
int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length);
/* send a group action
* return 0 on success
* return -1 on failure
*/
int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length);
/* set the group's title, limited to MAX_NAME_LENGTH
* return 0 on success
* return -1 on failure
*/
int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length);
/* Get group title from groupnumber and put it in title.
* title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
*
* return length of copied title if success.
* return -1 if failure.
*/
int tox_group_get_title(Tox *tox, int groupnumber, uint8_t *title, uint32_t max_length);
/* Check if the current peernumber corresponds to ours.
*
* return 1 if the peernumber corresponds to ours.
* return 0 on failure.
*/
unsigned int tox_group_peernumber_is_ours(const Tox *tox, int groupnumber, int peernumber);
/* Return the number of peers in the group chat on success.
* return -1 on failure
*/
int tox_group_number_peers(const Tox *tox, int groupnumber);
/* List all the peers in the group chat.
*
* Copies the names of the peers to the name[length][TOX_MAX_NAME_LENGTH] array.
*
* Copies the lengths of the names to lengths[length]
*
* returns the number of peers on success.
*
* return -1 on failure.
*/
int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX_NAME_LENGTH], uint16_t lengths[],
uint16_t length);
/* Return the number of chats in the instance m.
* You should use this to determine how much memory to allocate
* for copy_chatlist. */
uint32_t tox_count_chatlist(const Tox *tox);
/* Copy a list of valid chat IDs into the array out_list.
* If out_list is NULL, returns 0.
* Otherwise, returns the number of elements copied.
* If the array was too small, the contents
* of out_list will be truncated to list_size. */
uint32_t tox_get_chatlist(const Tox *tox, int32_t *out_list, uint32_t list_size);
/* return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
*
* return -1 on failure.
* return type on success.
*/
int tox_group_get_type(const Tox *tox, int groupnumber);

237
toxcore/tox_old_code.h Normal file
View File

@ -0,0 +1,237 @@
/**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/
/* Set the callback for group invites.
*
* Function(Tox *tox, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
*
* data of length is what needs to be passed to join_groupchat().
*/
void tox_callback_group_invite(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, const uint8_t *, uint16_t,
void *), void *userdata)
{
Messenger *m = tox;
g_callback_group_invite(m->group_chat_object, function, userdata);
}
/* Set the callback for group messages.
*
* Function(Tox *tox, int groupnumber, int peernumber, uint8_t * message, uint16_t length, void *userdata)
*/
void tox_callback_group_message(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint16_t, void *),
void *userdata)
{
Messenger *m = tox;
g_callback_group_message(m->group_chat_object, function, userdata);
}
/* Set the callback for group actions.
*
* Function(Tox *tox, int groupnumber, int peernumber, uint8_t * action, uint16_t length, void *userdata)
*/
void tox_callback_group_action(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint16_t, void *),
void *userdata)
{
Messenger *m = tox;
g_callback_group_action(m->group_chat_object, function, userdata);
}
/* Set callback function for title changes.
*
* Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata)
* if peernumber == -1, then author is unknown (e.g. initial joining the group)
*/
void tox_callback_group_title(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint8_t,
void *), void *userdata)
{
Messenger *m = tox;
g_callback_group_title(m->group_chat_object, function, userdata);
}
/* Set callback function for peer name list changes.
*
* It gets called every time the name list changes(new peer/name, deleted peer)
* Function(Tox *tox, int groupnumber, void *userdata)
*/
void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata)
{
Messenger *m = tox;
g_callback_group_namelistchange(m->group_chat_object, function, userdata);
}
/* Creates a new groupchat and puts it in the chats array.
*
* return group number on success.
* return -1 on failure.
*/
int tox_add_groupchat(Tox *tox)
{
Messenger *m = tox;
return add_groupchat(m->group_chat_object, GROUPCHAT_TYPE_TEXT);
}
/* Delete a groupchat from the chats array.
*
* return 0 on success.
* return -1 if failure.
*/
int tox_del_groupchat(Tox *tox, int groupnumber)
{
Messenger *m = tox;
return del_groupchat(m->group_chat_object, groupnumber);
}
/* Copy the name of peernumber who is in groupnumber to name.
* name must be at least MAX_NICK_BYTES long.
*
* return length of name if success
* return -1 if failure
*/
int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name)
{
const Messenger *m = tox;
return group_peername(m->group_chat_object, groupnumber, peernumber, name);
}
/* Copy the public key of peernumber who is in groupnumber to public_key.
* public_key must be crypto_box_PUBLICKEYBYTES long.
*
* returns 0 on success
* returns -1 on failure
*/
int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key)
{
const Messenger *m = tox;
return group_peer_pubkey(m->group_chat_object, groupnumber, peernumber, public_key);
}
/* invite friendnumber to groupnumber
* return 0 on success
* return -1 on failure
*/
int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
{
Messenger *m = tox;
return invite_friend(m->group_chat_object, friendnumber, groupnumber);
}
/* Join a group (you need to have been invited first.) using data of length obtained
* in the group invite callback.
*
* returns group number on success
* returns -1 on failure.
*/
int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length)
{
Messenger *m = tox;
return join_groupchat(m->group_chat_object, friendnumber, GROUPCHAT_TYPE_TEXT, data, length);
}
/* send a group message
* return 0 on success
* return -1 on failure
*/
int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length)
{
Messenger *m = tox;
return group_message_send(m->group_chat_object, groupnumber, message, length);
}
/* send a group action
* return 0 on success
* return -1 on failure
*/
int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length)
{
Messenger *m = tox;
return group_action_send(m->group_chat_object, groupnumber, action, length);
}
/* set the group's title, limited to MAX_NAME_LENGTH
* return 0 on success
* return -1 on failure
*/
int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length)
{
Messenger *m = tox;
return group_title_send(m->group_chat_object, groupnumber, title, length);
}
/* Get group title from groupnumber and put it in title.
* title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
*
* return length of copied title if success.
* return -1 if failure.
*/
int tox_group_get_title(Tox *tox, int groupnumber, uint8_t *title, uint32_t max_length)
{
Messenger *m = tox;
return group_title_get(m->group_chat_object, groupnumber, title, max_length);
}
/* Check if the current peernumber corresponds to ours.
*
* return 1 if the peernumber corresponds to ours.
* return 0 on failure.
*/
unsigned int tox_group_peernumber_is_ours(const Tox *tox, int groupnumber, int peernumber)
{
const Messenger *m = tox;
return group_peernumber_is_ours(m->group_chat_object, groupnumber, peernumber);
}
/* Return the number of peers in the group chat on success.
* return -1 on failure
*/
int tox_group_number_peers(const Tox *tox, int groupnumber)
{
const Messenger *m = tox;
return group_number_peers(m->group_chat_object, groupnumber);
}
/* List all the peers in the group chat.
*
* Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
*
* Copies the lengths of the names to lengths[length]
*
* returns the number of peers on success.
*
* return -1 on failure.
*/
int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX_NAME_LENGTH], uint16_t lengths[],
uint16_t length)
{
const Messenger *m = tox;
return group_names(m->group_chat_object, groupnumber, names, lengths, length);
}
/* Return the number of chats in the instance m.
* You should use this to determine how much memory to allocate
* for copy_chatlist. */
uint32_t tox_count_chatlist(const Tox *tox)
{
const Messenger *m = tox;
return count_chatlist(m->group_chat_object);
}
/* Copy a list of valid chat IDs into the array out_list.
* If out_list is NULL, returns 0.
* Otherwise, returns the number of elements copied.
* If the array was too small, the contents
* of out_list will be truncated to list_size. */
uint32_t tox_get_chatlist(const Tox *tox, int32_t *out_list, uint32_t list_size)
{
const Messenger *m = tox;
return copy_chatlist(m->group_chat_object, out_list, list_size);
}
/* return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
*
* return -1 on failure.
* return type on success.
*/
int tox_group_get_type(const Tox *tox, int groupnumber)
{
const Messenger *m = tox;
return group_get_type(m->group_chat_object, groupnumber);
}

2
toxencryptsave/defines.h Normal file
View File

@ -0,0 +1,2 @@
#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave"
#define TOX_ENC_SAVE_MAGIC_LENGTH 8

View File

@ -26,8 +26,10 @@
#endif
#include "toxencryptsave.h"
#include "defines.h"
#include "../toxcore/crypto_core.h"
#include "../toxcore/tox.h"
#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
#ifdef VANILLA_NACL
#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
@ -64,7 +66,7 @@ int tox_pass_salt_length()
/* return size of the messenger data (for encrypted saving). */
uint32_t tox_encrypted_size(const Tox *tox)
{
return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
return tox_get_savedata_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
}
/* This retrieves the salt used to encrypt the given data, which can then be passed to
@ -203,9 +205,9 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase
int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength)
{
/* first get plain save data */
uint32_t temp_size = tox_size(tox);
uint32_t temp_size = tox_get_savedata_size(tox);
uint8_t temp_data[temp_size];
tox_save(tox, temp_data);
tox_get_savedata(tox, temp_data);
/* now encrypt */
return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
@ -220,9 +222,9 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
{
/* first get plain save data */
uint32_t temp_size = tox_size(tox);
uint32_t temp_size = tox_get_savedata_size(tox);
uint8_t temp_data[temp_size];
tox_save(tox, temp_data);
tox_get_savedata(tox, temp_data);
/* encrypt */
return tox_pass_key_encrypt(temp_data, temp_size, key, data);
@ -292,38 +294,44 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase,
return tox_pass_key_decrypt(data, length, key, out);
}
/* Load the messenger from encrypted data of size length.
/* Load the new messenger from encrypted data of size length.
* All other arguments are like toxcore/tox_new().
*
* returns 0 on success
* returns -1 on failure
* returns NULL on failure; see the documentation in toxcore/tox.h.
*/
int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase,
size_t pplength, TOX_ERR_NEW *error)
{
uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
uint8_t temp_data[decrypt_length];
if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data)
!= decrypt_length)
return -1;
!= decrypt_length) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED);
return NULL;
}
return tox_load(tox, temp_data, decrypt_length);
return tox_new(options, temp_data, decrypt_length, error);
}
/* Load the messenger from encrypted data of size length, with key from tox_derive_key.
* All other arguments are like toxcore/tox_new().
*
* returns 0 on success
* returns -1 on failure
* returns NULL on failure; see the documentation in toxcore/tox.h.
*/
int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key)
Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key,
TOX_ERR_NEW *error)
{
uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
uint8_t temp_data[decrypt_length];
if (tox_pass_key_decrypt(data, length, key, temp_data)
!= decrypt_length)
return -1;
!= decrypt_length) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED);
return NULL;
}
return tox_load(tox, temp_data, decrypt_length);
return tox_new(options, temp_data, decrypt_length, error);
}
/* Determines whether or not the given data is encrypted (by checking the magic number)
@ -338,8 +346,3 @@ int tox_is_data_encrypted(const uint8_t *data)
else
return 0;
}
int tox_is_save_encrypted(const uint8_t *data)
{
return tox_is_data_encrypted(data);
}

View File

@ -29,10 +29,13 @@ extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#ifndef __TOX_DEFINED__
#define __TOX_DEFINED__
#ifndef TOX_DEFINED
#define TOX_DEFINED
typedef struct Tox Tox;
struct Tox_Options;
typedef enum TOX_ERR_NEW TOX_ERR_NEW;
#endif
// these functions provide access to these defines in toxencryptsave.c, which
@ -88,6 +91,9 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase
/* Save the messenger data encrypted with the given password.
* data must be at least tox_encrypted_size().
*
* NOTE: Unlike tox_save(), this function may fail. Be sure to check its return
* value.
*
* returns 0 on success
* returns -1 on failure
*/
@ -104,12 +110,13 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
*/
int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out);
/* Load the messenger from encrypted data of size length.
/* Load the new messenger from encrypted data of size length.
* All other arguments are like toxcore/tox_new().
*
* returns 0 on success
* returns -1 on failure
* returns NULL on failure; see the documentation in toxcore/tox.h.
*/
int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength);
Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase,
size_t pplength, TOX_ERR_NEW *error);
/******************************* BEGIN PART 1 *******************************
@ -161,6 +168,9 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
/* Save the messenger data encrypted with the given key from tox_derive_key.
* data must be at least tox_encrypted_size().
*
* NOTE: Unlike tox_save(), this function may fail. Be sure to check its return
* value.
*
* returns 0 on success
* returns -1 on failure
*/
@ -175,11 +185,13 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key);
int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out);
/* Load the messenger from encrypted data of size length, with key from tox_derive_key.
* All other arguments are like toxcore/tox_new().
*
* returns 0 on success
* returns -1 on failure
* returns NULL on failure; see the documentation in toxcore/tox.h.
*/
int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key);
Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key,
TOX_ERR_NEW *error);
/* Determines whether or not the given data is encrypted (by checking the magic number)
*
@ -187,7 +199,6 @@ int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8
* returns 0 otherwise
*/
int tox_is_data_encrypted(const uint8_t *data);
int tox_is_save_encrypted(const uint8_t *data); // poorly-named alias for backwards compat (oh irony...)
#ifdef __cplusplus
}