From 30524bf41513a334f0e32117b85aad2f661eed2b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 27 Aug 2014 15:13:44 -0400 Subject: [PATCH 001/101] Changed how receipts work. Messages now have a maximum length of 1372. Receipt packets have been removed, instead net_crypto tells us if the other peer has received the packets or not. --- toxcore/Messenger.c | 222 +++++++++++++++++++++++--------------------- toxcore/Messenger.h | 25 ++--- toxcore/tox.h | 2 +- 3 files changed, 128 insertions(+), 121 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fd7527e4..eff845cf 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -42,6 +42,7 @@ static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, uint32_t length); +static int clear_receipts(Messenger *m, int32_t friendnumber); // friend_not_valid determines if the friendnumber passed is valid in the Messenger object static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) @@ -251,7 +252,6 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u memcpy(m->friendlist[i].info, data, length); m->friendlist[i].info_size = length; m->friendlist[i].message_id = 0; - m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); @@ -301,7 +301,6 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) m->friendlist[i].userstatus = USERSTATUS_NONE; m->friendlist[i].is_typing = 0; m->friendlist[i].message_id = 0; - m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); if (m->numfriends == i) @@ -330,6 +329,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber) onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); + clear_receipts(m, friendnumber); remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); uint32_t i; @@ -363,6 +363,106 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) return m->friendlist[friendnumber].status > NOFRIEND; } +static int clear_receipts(Messenger *m, int32_t friendnumber) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; + + while (receipts) { + struct Receipts *temp_r = receipts->next; + free(receipts); + receipts = temp_r; + } + + m->friendlist[friendnumber].receipts_start = NULL; + m->friendlist[friendnumber].receipts_end = NULL; + return 0; +} + +static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *new = calloc(1, sizeof(struct Receipts)); + + if (!new) + return -1; + + new->packet_num = packet_num; + new->msg_id = msg_id; + + if (!m->friendlist[friendnumber].receipts_start) { + m->friendlist[friendnumber].receipts_start = new; + } else { + m->friendlist[friendnumber].receipts_end->next = new; + } + + m->friendlist[friendnumber].receipts_end = new; + new->next = NULL; + return 0; +} + +static int do_receipts(Messenger *m, int32_t friendnumber) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; + + while (receipts) { + struct Receipts *temp_r = receipts->next; + + if (cryptpacket_received(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, receipts->packet_num) == -1) + break; + + if (m->read_receipt) + (*m->read_receipt)(m, friendnumber, receipts->msg_id, m->read_receipt_userdata); + + free(receipts); + m->friendlist[friendnumber].receipts_start = temp_r; + receipts = temp_r; + } + + if (!m->friendlist[friendnumber].receipts_start) + m->friendlist[friendnumber].receipts_end = NULL; + + return 0; +} + +static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, + uint8_t packet_id) +{ + if (friend_not_valid(m, friendnumber)) + return 0; + + if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) + return 0; + + uint8_t packet[length + 1]; + packet[0] = packet_id; + + if (length != 0) + memcpy(packet + 1, message, length); + + int64_t packet_num = write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, + length + 1); + + if (packet_num == -1) + return 0; + + uint32_t msg_id = ++m->friendlist[friendnumber].message_id; + + if (msg_id == 0) { + msg_id = ++m->friendlist[friendnumber].message_id; // Otherwise, false error + } + + add_receipt(m, friendnumber, packet_num, msg_id); + return msg_id; +} + /* Send a text chat message to an online friend. * * return the message id if packet was successfully put into the send queue. @@ -370,32 +470,7 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) */ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length) { - if (friend_not_valid(m, friendnumber)) - return 0; - - uint32_t msgid = ++m->friendlist[friendnumber].message_id; - - if (msgid == 0) - msgid = 1; // Otherwise, false error - - if (m_sendmessage_withid(m, friendnumber, msgid, message, length)) { - return msgid; - } - - return 0; -} - -uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message, - uint32_t length) -{ - if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0) - return 0; - - uint8_t temp[sizeof(theid) + length]; - theid = htonl(theid); - memcpy(temp, &theid, sizeof(theid)); - memcpy(temp + sizeof(theid), message, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, sizeof(temp)); + return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE); } /* Send an action to an online friend. @@ -405,32 +480,7 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid */ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length) { - if (friend_not_valid(m, friendnumber)) - return 0; - - uint32_t msgid = ++m->friendlist[friendnumber].message_id; - - if (msgid == 0) - msgid = 1; // Otherwise, false error - - if (m_sendaction_withid(m, friendnumber, msgid, action, length)) { - return msgid; - } - - return 0; -} - -uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action, - uint32_t length) -{ - if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0) - return 0; - - uint8_t temp[sizeof(theid) + length]; - theid = htonl(theid); - memcpy(temp, &theid, sizeof(theid)); - memcpy(temp + sizeof(theid), action, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, temp, sizeof(temp)); + return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION); } /* Send a name packet to friendnumber. @@ -725,18 +775,6 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t m->friendlist[friendnumber].is_typing = is_typing; } -/* Sets whether we send read receipts for friendnumber. */ -void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno) -{ - if (yesno != 0 && yesno != 1) - return; - - if (friend_not_valid(m, friendnumber)) - return; - - m->friendlist[friendnumber].receives_read_receipts = yesno; -} - /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */ /* Set the function that will be executed when a friend request is received. */ void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, uint16_t, @@ -821,6 +859,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui if (was_online) { break_files(m, friendnumber); remove_online_friend(m, friendnumber); + clear_receipts(m, friendnumber); } else { add_online_friend(m, friendnumber); } @@ -842,8 +881,8 @@ void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status) m->friendlist[friendnumber].status = status; } -int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, - uint32_t length) +static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, + uint32_t length) { if (friend_not_valid(m, friendnumber)) return 0; @@ -1916,8 +1955,8 @@ void kill_messenger(Messenger *m) kill_networking(m->net); for (i = 0; i < m->numfriends; ++i) { - if (m->friendlist[i].statusmessage) - free(m->friendlist[i].statusmessage); + clear_receipts(m, i); + free(m->friendlist[i].statusmessage); } free(m->friendlist); @@ -2051,24 +2090,17 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_MESSAGE: { - const uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) + if (data_length == 0) break; - const uint8_t *message = data + message_id_length; - uint16_t message_length = data_length - message_id_length; + const uint8_t *message = data; + uint16_t message_length = data_length; /* Make sure the NULL terminator is present. */ uint8_t message_terminated[message_length + 1]; memcpy(message_terminated, message, message_length); message_terminated[message_length] = 0; - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - if (m->friend_message) (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); @@ -2076,24 +2108,17 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_ACTION: { - const uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) + if (data_length == 0) break; - const uint8_t *action = data + message_id_length; - uint16_t action_length = data_length - message_id_length; + const uint8_t *action = data; + uint16_t action_length = data_length; /* Make sure the NULL terminator is present. */ uint8_t action_terminated[action_length + 1]; memcpy(action_terminated, action, action_length); action_terminated[action_length] = 0; - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - if (m->friend_action) (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); @@ -2101,21 +2126,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; } - case PACKET_ID_RECEIPT: { - uint32_t msgid; - - if (data_length < sizeof(msgid)) - break; - - memcpy(&msgid, data, sizeof(msgid)); - msgid = ntohl(msgid); - - if (m->read_receipt) - (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); - - break; - } - case PACKET_ID_INVITE_GROUPCHAT: { if (data_length != crypto_box_PUBLICKEYBYTES) break; @@ -2348,6 +2358,8 @@ void do_friends(Messenger *m) if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) { send_relays(m, i); } + + do_receipts(m, i); } } } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c45eaff9..c9f3cf88 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -46,7 +46,6 @@ #define PACKET_ID_STATUSMESSAGE 49 #define PACKET_ID_USERSTATUS 50 #define PACKET_ID_TYPING 51 -#define PACKET_ID_RECEIPT 63 #define PACKET_ID_MESSAGE 64 #define PACKET_ID_ACTION 65 #define PACKET_ID_MSI 69 @@ -74,6 +73,13 @@ typedef struct { TCP_Proxy_Info proxy_info; } Messenger_Options; + +struct Receipts { + uint32_t packet_num; + uint32_t msg_id; + struct Receipts *next; +}; + /* Status definitions. */ enum { NOFRIEND, @@ -168,7 +174,6 @@ typedef struct { 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; uint64_t ping_lastsent; @@ -187,6 +192,9 @@ typedef struct { int (*function)(void *object, const uint8_t *data, uint32_t len); void *object; } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; + + struct Receipts *receipts_start; + struct Receipts *receipts_end; } Friend; @@ -335,12 +343,8 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber); * * 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. */ 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); /* Send an action to an online friend. * @@ -349,12 +353,8 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid * * 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. @@ -453,11 +453,6 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t 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); - /* 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) */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 550600f9..08c2b3a2 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -34,7 +34,7 @@ extern "C" { #define TOX_MAX_NAME_LENGTH 128 /* Maximum length of single messages after which they should be split. */ -#define TOX_MAX_MESSAGE_LENGTH 1368 +#define TOX_MAX_MESSAGE_LENGTH 1372 #define TOX_MAX_STATUSMESSAGE_LENGTH 1007 #define TOX_CLIENT_ID_SIZE 32 From eac0d435f35db468435fa596a3b00b593d6bf3e9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Feb 2015 16:18:02 -0500 Subject: [PATCH 002/101] Started implementing new Tox api. --- toxcore/tox.c | 1072 +------------------- toxcore/tox.h | 2622 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 1820 insertions(+), 1874 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 82beb561..124d7119 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -29,1078 +29,78 @@ #include "group.h" #include "logger.h" -#define __TOX_DEFINED__ +#define TOX_DEFINED typedef struct Messenger Tox; #include "tox.h" -/* - * returns a FRIEND_ADDRESS_SIZE byte address to give to others. - * Format: [public_key (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] - * - */ -void tox_get_address(const Tox *tox, uint8_t *address) -{ - const Messenger *m = tox; - getaddress(m, address); -} - -/* - * Add a friend. - * Set the data that will be sent along with friend request. - * address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum. - * data is the data and length is the length. - * - * return the friend number if success. - * return FA_TOOLONG if message length is too long. - * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte). - * return FAERR_OWNKEY if user's own key. - * return FAERR_ALREADYSENT if friend request already sent or already a friend. - * return FAERR_UNKNOWN for unknown error. - * return FAERR_BADCHECKSUM if bad checksum in address. - * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different. - * (the nospam for that friend was set to the new one). - * return FAERR_NOMEM if increasing the friend list size fails. - */ -int32_t tox_add_friend(Tox *tox, const uint8_t *address, const uint8_t *data, uint16_t length) -{ - Messenger *m = tox; - return m_addfriend(m, address, data, length); -} - -/* Add a friend without sending a friendrequest. - * - * return the friend number if success. - * return -1 if failure. - */ -int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *public_key) -{ - Messenger *m = tox; - return m_addfriend_norequest(m, public_key); -} - -/* return the friend number associated to that client id. - * return -1 if no such friend. - */ -int32_t tox_get_friend_number(const Tox *tox, const uint8_t *public_key) -{ - const Messenger *m = tox; - return getfriend_id(m, public_key); -} - -/* Copies the public key associated to that friend id into public_key buffer. - * Make sure that public_key is of size crypto_box_PUBLICKEYBYTES. - * - * return 0 if success. - * return -1 if failure. - */ -int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *public_key) -{ - const Messenger *m = tox; - return get_real_pk(m, friendnumber, public_key); -} - -/* Remove a friend. */ -int tox_del_friend(Tox *tox, int32_t friendnumber) -{ - Messenger *m = tox; - return m_delfriend(m, 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 -1 on failure. - */ -int tox_get_friend_connection_status(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_friend_connectionstatus(m, friendnumber); -} - -/* Checks if there exists a friend with given friendnumber. - * - * return 1 if friend exists. - * return 0 if friend doesn't exist. - */ -int tox_friend_exists(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_friend_exists(m, friendnumber); -} - -/* Send a text chat message 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. - */ -uint32_t tox_send_message(Tox *tox, int32_t friendnumber, const uint8_t *message, uint32_t length) -{ - Messenger *m = tox; - return m_sendmessage(m, friendnumber, message, length); -} - -/* 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. - */ -uint32_t tox_send_action(Tox *tox, int32_t friendnumber, const uint8_t *action, uint32_t length) -{ - Messenger *m = tox; - return m_sendaction(m, friendnumber, action, length); -} - -/* Set our nickname. - * name must be a string of maximum MAX_NAME_LENGTH length. - * length must be at least 1 byte. - * length is the length of name with the NULL terminator. - * - * return 0 if success. - * return -1 if failure. - */ -int tox_set_name(Tox *tox, const uint8_t *name, uint16_t length) -{ - Messenger *m = tox; - - if (setname(m, name, length) == 0) { - send_name_all_groups(m->group_chat_object); - return 0; - } else { - return -1; - } -} - -/* Get your nickname. - * m - The messenger context to use. - * name - Pointer to a string for the name. (must be at least MAX_NAME_LENGTH) - * - * return length of the name. - * return 0 on error. - */ -uint16_t tox_get_self_name(const Tox *tox, uint8_t *name) -{ - const Messenger *m = tox; - return getself_name(m, name); -} - -/* Get name of friendnumber and put it in name. - * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. - * - * return length of name (with the NULL terminator) if success. - * return -1 if failure. - */ -int tox_get_name(const Tox *tox, int32_t friendnumber, uint8_t *name) -{ - const Messenger *m = tox; - return getname(m, friendnumber, name); -} - -/* returns the length of name on success. - * returns -1 on failure. - */ -int tox_get_name_size(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_name_size(m, friendnumber); -} - -int tox_get_self_name_size(const Tox *tox) -{ - const Messenger *m = tox; - return m_get_self_name_size(m); -} - -/* Set our user status; - * you are responsible for freeing status after. - * - * return 0 on success, -1 on failure. - */ -int tox_set_status_message(Tox *tox, const uint8_t *status, uint16_t length) -{ - Messenger *m = tox; - return m_set_statusmessage(m, status, length); -} - -int tox_set_user_status(Tox *tox, uint8_t status) -{ - Messenger *m = tox; - return m_set_userstatus(m, status); -} - -/* returns the length of status message on success. - * returns -1 on failure. - */ -int tox_get_status_message_size(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_statusmessage_size(m, friendnumber); -} - -int tox_get_self_status_message_size(const Tox *tox) -{ - const Messenger *m = tox; - return m_get_self_statusmessage_size(m); -} - -/* Copy friendnumber's status message into buf, truncating if size is over maxlen. - * Get the size you need to allocate from m_get_statusmessage_size. - * The self variant will copy our own status message. - */ -int tox_get_status_message(const Tox *tox, int32_t friendnumber, uint8_t *buf, uint32_t maxlen) -{ - const Messenger *m = tox; - return m_copy_statusmessage(m, friendnumber, buf, maxlen); -} - -int tox_get_self_status_message(const Tox *tox, uint8_t *buf, uint32_t maxlen) -{ - const Messenger *m = tox; - return m_copy_self_statusmessage(m, buf, maxlen); -} - -/* Return one of USERSTATUS values. - * Values unknown to your application should be represented as USERSTATUS_NONE. - * As above, the self variant will return our own USERSTATUS. - * If friendnumber is invalid, this shall return USERSTATUS_INVALID. - */ -uint8_t tox_get_user_status(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_userstatus(m, friendnumber); -} - -uint8_t tox_get_self_user_status(const Tox *tox) -{ - const Messenger *m = tox; - return m_get_self_userstatus(m); -} - -/* returns timestamp of last time friendnumber was seen online, or 0 if never seen. - * returns -1 on error. - */ -uint64_t tox_get_last_online(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_last_online(m, friendnumber); -} - -/* Set our typing status for a friend. - * You are responsible for turning it on or off. - * - * returns 0 on success. - * returns -1 on failure. - */ -int tox_set_user_is_typing(Tox *tox, int32_t friendnumber, uint8_t is_typing) -{ - Messenger *m = tox; - return m_set_usertyping(m, friendnumber, is_typing); -} - -/* Get the typing status of a friend. - * - * returns 0 if friend is not typing. - * returns 1 if friend is typing. - */ -uint8_t tox_get_is_typing(const Tox *tox, int32_t friendnumber) -{ - const Messenger *m = tox; - return m_get_istyping(m, friendnumber); -} - -/* Return the number of friends in the instance m. - * You should use this to determine how much memory to allocate - * for copy_friendlist. */ -uint32_t tox_count_friendlist(const Tox *tox) -{ - const Messenger *m = tox; - return count_friendlist(m); -} - -/* Return the number of online friends in the instance m. */ -uint32_t tox_get_num_online_friends(const Tox *tox) -{ - const Messenger *m = tox; - return get_num_online_friends(m); -} - -/* Copy a list of valid friend IDs into the array out_list. - * If out_list is NULL, returns 0. - * Otherwise, returns the number of elements copied. - * If the array was too small, the contents - * of out_list will be truncated to list_size. */ -uint32_t tox_get_friendlist(const Tox *tox, int32_t *out_list, uint32_t list_size) -{ - const Messenger *m = tox; - return copy_friendlist(m, out_list, list_size); -} - -/* 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) - */ -void tox_callback_friend_request(Tox *tox, void (*function)(Tox *tox, const uint8_t *, const uint8_t *, uint16_t, - void *), void *userdata) -{ - Messenger *m = tox; - m_callback_friendrequest(m, function, 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) - */ -void tox_callback_friend_message(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_friendmessage(m, function, 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 tox_callback_friend_action(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_action(m, function, userdata); -} - -/* Set the callback for name changes. - * function(int32_t friendnumber, uint8_t *newname, uint16_t length) - * You are not responsible for freeing newname. - */ -void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_namechange(m, function, userdata); -} - -/* Set the callback for status message changes. - * function(int32_t friendnumber, uint8_t *newstatus, uint16_t length) - * You are not responsible for freeing newstatus. - */ -void tox_callback_status_message(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_statusmessage(m, function, userdata); -} - -/* Set the callback for status type changes. - * function(int32_t friendnumber, USERSTATUS kind) - */ -void tox_callback_user_status(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_userstatus(m, function, userdata); -} - -/* Set the callback for typing changes. - * function (int32_t friendnumber, uint8_t is_typing) - */ -void tox_callback_typing_change(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, void *), void *userdata) -{ - Messenger *m = tox; - m_callback_typingchange(m, function, userdata); -} - -/* Set the callback for read receipts. - * function(int32_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 - * has been received on the other side. - * Since core doesn't track ids for you, receipt may not correspond to any message. - * in that case, you should discard it. - */ -void tox_callback_read_receipt(Tox *tox, void (*function)(Messenger *tox, int32_t, uint32_t, void *), void *userdata) -{ - Messenger *m = tox; - m_callback_read_receipt(m, function, userdata); -} - -/* Set the callback for connection status changes. - * function(int32_t friendnumber, uint8_t status) - * - * Status: - * 0 -- friend went offline after being previously online - * 1 -- friend went online - * - * NOTE: this callback is not called when adding friends, thus the "after - * being previously online" part. It's assumed that when adding friends, - * their connection status is offline. - */ -void tox_callback_connection_status(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, void *), - void *userdata) -{ - Messenger *m = tox; - m_callback_connectionstatus(m, function, userdata); -} - -/**********ADVANCED FUNCTIONS (If you don't know what they do you can safely ignore them.) ************/ - -/* Functions to get/set the nospam part of the id. - */ -uint32_t tox_get_nospam(const Tox *tox) -{ - const Messenger *m = tox; - return get_nospam(&(m->fr)); -} - -void tox_set_nospam(Tox *tox, uint32_t nospam) -{ - Messenger *m = tox; - set_nospam(&(m->fr), nospam); -} - -/* Copy the public and secret key from the Tox object. - public_key and secret_key must be 32 bytes big. - if the pointer is NULL, no data will be copied to it.*/ -void tox_get_keys(Tox *tox, uint8_t *public_key, uint8_t *secret_key) -{ - Messenger *m = tox; - - if (public_key) - memcpy(public_key, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); - - if (secret_key) - memcpy(secret_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); -} - -/* Set handlers for custom lossy packets. - * Set the function to be called when friend sends us a lossy packet starting with byte. - * byte must be in the 200-254 range. - * - * NOTE: lossy packets behave like UDP packets meaning they might never reach the other side - * or might arrive more than once (if someone is messing with the connection) or might arrive - * in the wrong order. - * - * Unless latency is an issue, it is recommended that you use lossless packets instead. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_lossy_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Messenger *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), - void *object) -{ - Messenger *m = tox; +#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} - if (byte < (PACKET_ID_LOSSY_RANGE_START + 8)) /* First 8 reserved for A/V*/ - return -1; - - return custom_lossy_packet_registerhandler(m, friendnumber, byte, packet_handler_callback, object); -} - -/* Function to send custom lossy packets. - * First byte of data must be in the range: 200-254. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_send_lossy_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length) -{ - const Messenger *m = tox; - - if (length == 0) - return -1; - - if (data[0] < (PACKET_ID_LOSSY_RANGE_START + 8)) /* First 8 reserved for A/V*/ - return -1; - - return send_custom_lossy_packet(m, friendnumber, data, length); -} - -/* Set handlers for custom lossless packets. - * Set the function to be called when friend sends us a lossless packet starting with byte. - * byte must be in the 160-191 range. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_lossless_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Messenger *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), - void *object) -{ - Messenger *m = tox; - - return custom_lossless_packet_registerhandler(m, friendnumber, byte, packet_handler_callback, object); -} - -/* Function to send custom lossless packets. - * First byte of data must be in the range: 160-191. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length) -{ - const Messenger *m = tox; - - return send_custom_lossless_packet(m, friendnumber, data, length); -} - -/**********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) +uint32_t tox_version_major(void) { - Messenger *m = tox; - return add_groupchat(m->group_chat_object, GROUPCHAT_TYPE_TEXT); + return 0; } -/* Delete a groupchat from the chats array. - * - * return 0 on success. - * return -1 if failure. - */ -int tox_del_groupchat(Tox *tox, int groupnumber) +uint32_t tox_version_minor(void) { - Messenger *m = tox; - return del_groupchat(m->group_chat_object, groupnumber); + return 0; } -/* 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) +uint32_t tox_version_patch(void) { - const Messenger *m = tox; - return group_peername(m->group_chat_object, groupnumber, peernumber, name); + return 0; } -/* 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) +bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch) { - 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); -} - -/****************FILE SENDING FUNCTIONS*****************/ - - -/* 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) - */ -void tox_callback_file_send_request(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, uint64_t, - const uint8_t *, uint16_t, void *), void *userdata) -{ - Messenger *m = tox; - callback_file_sendrequest(m, function, 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) - * - */ -void tox_callback_file_control(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, uint8_t, uint8_t, - const uint8_t *, uint16_t, void *), void *userdata) -{ - Messenger *m = tox; - callback_file_control(m, function, userdata); -} -/* Set the callback for file data. - * - * Function(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) - * - */ -void tox_callback_file_data(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, const uint8_t *, - uint16_t length, void *), void *userdata) - -{ - Messenger *m = tox; - callback_file_data(m, function, userdata); -} -/* Send a file send request. - * Maximum filename length is 255 bytes. - * return file number on success - * return -1 on failure - */ -int tox_new_file_sender(Tox *tox, int32_t friendnumber, uint64_t filesize, const uint8_t *filename, - uint16_t filename_length) -{ - Messenger *m = tox; - return new_filesender(m, friendnumber, filesize, filename, 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 0 on success - * return -1 on failure - */ -int tox_file_send_control(Tox *tox, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, - const uint8_t *data, uint16_t length) -{ - Messenger *m = tox; - return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length); -} -/* Send file data. - * - * return 0 on success - * return -1 on failure - */ -int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length) -{ - Messenger *m = tox; - return file_data(m, friendnumber, filenumber, data, length); -} - -/* Returns the recommended/maximum size of the filedata you send with tox_file_send_data() - * - * return size on success - * return -1 on failure (currently will never return -1) - */ -int tox_file_data_size(const Tox *tox, int32_t friendnumber) -{ - return MAX_CRYPTO_DATA_SIZE - 2; -} - -/* Give the number of bytes left to be sent/received. - * - * send_receive is 0 if we want the sending files, 1 if we want the receiving. - * - * return number of bytes remaining to be sent/received on success - * return 0 on failure - */ -uint64_t tox_file_data_remaining(const Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive) -{ - const Messenger *m = tox; - return file_dataremaining(m, friendnumber, filenumber, send_receive); -} - - -/****************AVATAR FUNCTIONS*****************/ - -void tox_callback_avatar_info(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, void *), void *userdata) -{ - Messenger *m = tox; - m_callback_avatar_info(m, function, userdata); -} - -void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, - void *), void *userdata) -{ - Messenger *m = tox; - m_callback_avatar_data(m, function, userdata); -} - -int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length) -{ - Messenger *m = tox; - return m_set_avatar(m, format, data, length); -} - -int tox_unset_avatar(Tox *tox) -{ - Messenger *m = tox; - return m_unset_avatar(m); -} - -int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash) -{ - const Messenger *m = tox; - return m_get_self_avatar(m, format, buf, length, maxlen, hash); -} - -int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen) -{ - return m_hash(hash, data, datalen); -} - -int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber) -{ - const Messenger *m = tox; - return m_request_avatar_info(m, friendnumber); -} - -int tox_send_avatar_info(Tox *tox, const int32_t friendnumber) -{ - const Messenger *m = tox; - return m_send_avatar_info(m, friendnumber); -} - -int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber) -{ - const Messenger *m = tox; - return m_request_avatar_data(m, friendnumber); -} - -/***************END OF FILE SENDING FUNCTIONS******************/ - -/* Like tox_bootstrap_from_address but for TCP relays only. - * - * return 0 on failure. - * return 1 on success. - */ -int tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key) -{ - Messenger *m = tox; - IP_Port ip_port, ip_port_v4; - - if (!addr_parse_ip(address, &ip_port.ip)) { - if (m->options.udp_disabled) /* Disable DNS when udp is disabled. */ - return 0; - - IP *ip_extra = NULL; - ip_init(&ip_port.ip, m->options.ipv6enabled); - - if (m->options.ipv6enabled) { - /* setup for getting BOTH: an IPv6 AND an IPv4 address */ - ip_port.ip.family = AF_UNSPEC; - ip_reset(&ip_port_v4.ip); - ip_extra = &ip_port_v4.ip; - } - - if (!addr_resolve(address, &ip_port.ip, ip_extra)) - return 0; - } - - ip_port.port = htons(port); - add_tcp_relay(m->net_crypto, ip_port, public_key); - onion_add_bs_path_node(m->onion_c, ip_port, public_key); //TODO: move this + //TODO return 1; } -int tox_bootstrap_from_address(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key) -{ - Messenger *m = tox; - int ret = tox_add_tcp_relay(tox, address, port, public_key); - if (m->options.udp_disabled) { - return ret; - } else { /* DHT only works on UDP. */ - return DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key); +void tox_options_default(struct Tox_Options *options) +{ + if (options) { + memset(options, 0, sizeof(struct Tox_Options)); } } -/* return 0 if we are not connected to the DHT. - * return 1 if we are. - */ -int tox_isconnected(const Tox *tox) +struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error) { - const Messenger *m = tox; - return onion_isconnected(m->onion_c); -} + struct Tox_Options *options = calloc(sizeof(struct Tox_Options), 1); -/* Return the time in milliseconds before tox_do() should be called again - * for optimal performance. - * - * returns time (in ms) before the next tox_do() needs to be run on success. - */ -uint32_t tox_do_interval(Tox *tox) -{ - Messenger *m = tox; - return messenger_run_interval(m); -} - -/* Run this at startup. - * - * return allocated instance of tox on success. - * return 0 if there are problems. - */ -Tox *tox_new(Tox_Options *options) -{ - if (!logger_get_global()) - logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); - - Messenger_Options m_options = {0}; - - if (options == NULL) { - m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; - } else { - m_options.ipv6enabled = options->ipv6enabled; - m_options.udp_disabled = options->udp_disabled; - - switch (options->proxy_type) { - case TOX_PROXY_HTTP: - m_options.proxy_info.proxy_type = TCP_PROXY_HTTP; - break; - - case TOX_PROXY_SOCKS5: - m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5; - break; - - case TOX_PROXY_NONE: - m_options.proxy_info.proxy_type = TCP_PROXY_NONE; - break; - } - - if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) { - ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled); - - if (m_options.ipv6enabled) - m_options.proxy_info.ip_port.ip.family = AF_UNSPEC; - - if (!addr_resolve_or_parse_ip(options->proxy_address, &m_options.proxy_info.ip_port.ip, NULL)) - return NULL; - - m_options.proxy_info.ip_port.port = htons(options->proxy_port); - } + if (options) { + SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK); + return options; } - Messenger *m = new_messenger(&m_options); - - if (!new_groupchats(m)) { - kill_messenger(m); - return NULL; - } - - return m; + SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC); + return NULL; +} + +void tox_options_free(struct Tox_Options *options) +{ + free(options); +} + +Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t length, TOX_ERR_NEW *error) +{ + } -/* Run this before closing shop. - * Free all datastructures. - */ void tox_kill(Tox *tox) { - Messenger *m = tox; - kill_groupchats(m->group_chat_object); - kill_messenger(m); - logger_kill_global(); + } -/* The main loop that needs to be run at least 20 times per second. */ -void tox_do(Tox *tox) + +size_t tox_save_size(Tox const *tox) { - Messenger *m = tox; - do_messenger(m); - do_groupchats(m->group_chat_object); + } -/* SAVING AND LOADING FUNCTIONS: */ -/* return size of the messenger data (for saving). */ -uint32_t tox_size(const Tox *tox) +void tox_save(Tox const *tox, uint8_t *data) { - const Messenger *m = tox; - return messenger_size(m); -} -/* Save the messenger in data (must be allocated memory of size Messenger_size()). */ -void tox_save(const Tox *tox, uint8_t *data) -{ - const Messenger *m = tox; - messenger_save(m, data); -} - -/* Load the messenger from data of size length. */ -int tox_load(Tox *tox, const uint8_t *data, uint32_t length) -{ - if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) - return 1; - - Messenger *m = tox; - return messenger_load(m, data, length); } diff --git a/toxcore/tox.h b/toxcore/tox.h index ee678cc1..8dab7002 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -24,928 +24,1874 @@ #ifndef TOX_H #define TOX_H +#include +#include #include - #ifdef __cplusplus extern "C" { #endif -#define TOX_MAX_NAME_LENGTH 128 - -/* Maximum length of single messages after which they should be split. */ -#define TOX_MAX_MESSAGE_LENGTH 1368 -#define TOX_MAX_STATUSMESSAGE_LENGTH 1007 -#define TOX_MAX_FRIENDREQUEST_LENGTH 1016 - -#define TOX_PUBLIC_KEY_SIZE 32 -/* TODO: remove */ -#define TOX_CLIENT_ID_SIZE TOX_PUBLIC_KEY_SIZE - -#define TOX_AVATAR_MAX_DATA_LENGTH 16384 -#define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 - -#define TOX_FRIEND_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) - -#define TOX_ENABLE_IPV6_DEFAULT 1 - -#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave" -#define TOX_ENC_SAVE_MAGIC_LENGTH 8 - -/* Errors for m_addfriend - * FAERR - Friend Add Error +/** \page core Public core API for Tox clients. + * + * Every function that can fail takes a function-specific error code pointer + * that can be used to diagnose problems with the Tox state or the function + * arguments. The error code pointer can be NULL, which does not influence the + * function's behaviour, but can be done if the reason for failure is irrelevant + * to the client. + * + * The exception to this rule are simple allocation functions whose only failure + * mode is allocation failure. They return NULL in that case, and do not set an + * error code. + * + * Every error code type has an OK value to which functions will set their error + * code value on success. Clients can keep their error code uninitialised before + * passing it to a function. The library guarantees that after returning, the + * value pointed to by the error code pointer has been initialised. + * + * Functions with pointer parameters often have a NULL error code, meaning they + * could not perform any operation, because one of the required parameters was + * NULL. Some functions operate correctly or are defined as effectless on NULL. + * + * Some functions additionally return a value outside their + * return type domain, or a bool containing true on success and false on + * failure. + * + * All functions that take a Tox instance pointer will cause undefined behaviour + * when passed a NULL Tox pointer. + * + * All integer values are expected in host byte order. + * + * Functions with parameters with enum types cause unspecified behaviour if the + * enumeration value is outside the valid range of the type. If possible, the + * function will try to use a sane default, but there will be no error code, + * and one possible action for the function to take is to have no effect. */ -enum { - TOX_FAERR_TOOLONG = -1, - TOX_FAERR_NOMESSAGE = -2, - TOX_FAERR_OWNKEY = -3, - TOX_FAERR_ALREADYSENT = -4, - TOX_FAERR_UNKNOWN = -5, - TOX_FAERR_BADCHECKSUM = -6, - TOX_FAERR_SETNEWNOSPAM = -7, - TOX_FAERR_NOMEM = -8 -}; -/* USERSTATUS - - * Represents userstatuses someone can have. +/** \subsection events Events and callbacks + * + * Events are handled by callbacks. One callback can be registered per event. + * All events have a callback function type named `tox_${event}_cb` and a + * function to register it named `tox_callback_${event}`. Passing a NULL + * callback will result in no callback being registered for that event. Only + * one callback per event can be registered, so if a client needs multiple + * event listeners, it needs to implement the dispatch functionality itself. */ -typedef enum { - TOX_USERSTATUS_NONE, - TOX_USERSTATUS_AWAY, - TOX_USERSTATUS_BUSY, - TOX_USERSTATUS_INVALID -} -TOX_USERSTATUS; - -/* AVATAR_FORMAT - - * Data formats for user avatar images +/** \subsection threading Threading implications + * + * It is possible to run multiple concurrent threads with a Tox instance for + * each thread. It is also possible to run all Tox instances in the same thread. + * A common way to run Tox (multiple or single instance) is to have one thread + * running a simple tox_iteration loop, sleeping for tox_iteration_time + * milliseconds on each iteration. + * + * If you want to access a single Tox instance from multiple threads, access + * to the instance must be synchronised. While multiple threads can concurrently + * access multiple different Tox instances, no more than one API function can + * operate on a single instance at any given time. + * + * Functions that write to variable length byte arrays will always have a size + * function associated with them. The result of this size function is only valid + * until another mutating function (one that takes a pointer to non-const Tox) + * is called. Thus, clients must ensure that no other thread calls a mutating + * function between the call to the size function and the call to the retrieval + * function. + * + * E.g. to get the current nickname, one would write + * + * \code + * size_t length = tox_self_get_name_size(tox); + * uint8_t *name = malloc(length); + * if (!name) abort(); + * tox_self_get_name(tox, name); + * \endcode + * + * If any other thread calls tox_self_set_name while this thread is allocating + * memory, the length will have become invalid, and the call to + * tox_self_get_name may cause undefined behaviour. */ -typedef enum { - TOX_AVATAR_FORMAT_NONE = 0, - TOX_AVATAR_FORMAT_PNG -} -TOX_AVATAR_FORMAT; -#ifndef __TOX_DEFINED__ -#define __TOX_DEFINED__ +#ifndef TOX_DEFINED +#define TOX_DEFINED +/** + * The Tox instance type. All the state associated with a connection is held + * within the instance. Multiple instances can exist and operate concurrently. + * The maximum number of Tox instances that can exist on a single network + * device is limited. Note that this is not just a per-process limit, since the + * limiting factor is the number of usable ports on a device. + */ typedef struct Tox Tox; #endif -/* NOTE: Strings in Tox are all UTF-8, (This means that there is no terminating NULL character.) - * - * The exact buffer you send will be received at the other end without modification. - * - * Do not treat Tox strings as C strings. - */ - -/* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others. - * format: [public_key (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] - */ -void tox_get_address(const Tox *tox, uint8_t *address); - -/* Add a friend. - * Set the data that will be sent along with friend request. - * address is the address of the friend (returned by getaddress of the friend you wish to add) it must be TOX_FRIEND_ADDRESS_SIZE bytes. TODO: add checksum. - * data is the data and length is the length (maximum length of data is TOX_MAX_FRIENDREQUEST_LENGTH). - * - * return the friend number if success. - * return TOX_FAERR_TOOLONG if message length is too long. - * return TOX_FAERR_NOMESSAGE if no message (message length must be >= 1 byte). - * return TOX_FAERR_OWNKEY if user's own key. - * return TOX_FAERR_ALREADYSENT if friend request already sent or already a friend. - * return TOX_FAERR_UNKNOWN for unknown error. - * return TOX_FAERR_BADCHECKSUM if bad checksum in address. - * return TOX_FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different. - * (the nospam for that friend was set to the new one). - * return TOX_FAERR_NOMEM if increasing the friend list size fails. - */ -int32_t tox_add_friend(Tox *tox, const uint8_t *address, const uint8_t *data, uint16_t length); - - -/* Add a friend without sending a friendrequest. - * return the friend number if success. - * return -1 if failure. - */ -int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *public_key); - -/* return the friend number associated to that client id. - return -1 if no such friend */ -int32_t tox_get_friend_number(const Tox *tox, const uint8_t *public_key); - -/* Copies the public key associated to that friend id into public_key buffer. - * Make sure that public_key is of size TOX_PUBLIC_KEY_SIZE. - * return 0 if success. - * return -1 if failure. - */ -int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *public_key); - -/* Remove a friend. - * - * return 0 if success. - * return -1 if failure. - */ -int tox_del_friend(Tox *tox, 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 -1 on failure. - */ -int tox_get_friend_connection_status(const Tox *tox, int32_t friendnumber); - -/* Checks if there exists a friend with given friendnumber. - * - * return 1 if friend exists. - * return 0 if friend doesn't exist. - */ -int tox_friend_exists(const Tox *tox, int32_t friendnumber); - -/* Send a text chat message to an online friend. - * - * return the message id if packet was successfully put into the send queue. - * return 0 if it was not. - * - * maximum length of messages is TOX_MAX_MESSAGE_LENGTH, your client must split larger messages - * or else sending them will not work. No the core will not split messages for you because that - * requires me to parse UTF-8. - * - * You will want to retain the return value, it will be passed to your read_receipt callback - * if one is received. - */ -uint32_t tox_send_message(Tox *tox, int32_t friendnumber, const uint8_t *message, uint32_t length); - -/* 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. - * - * maximum length of actions is TOX_MAX_MESSAGE_LENGTH, your client must split larger actions - * or else sending them will not work. No the core will not split actions for you because that - * requires me to parse UTF-8. - * - * You will want to retain the return value, it will be passed to your read_receipt callback - * if one is received. - */ -uint32_t tox_send_action(Tox *tox, int32_t friendnumber, const uint8_t *action, uint32_t length); - -/* Set our nickname. - * name must be a string of maximum MAX_NAME_LENGTH length. - * length must be at least 1 byte. - * length is the length of name. - * - * return 0 if success. - * return -1 if failure. - */ -int tox_set_name(Tox *tox, const uint8_t *name, uint16_t length); - -/* - * Get your nickname. - * m - The messenger context to use. - * name - needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. - * - * return length of name. - * return 0 on error. - */ -uint16_t tox_get_self_name(const Tox *tox, uint8_t *name); - -/* Get name of friendnumber and put it in name. - * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. - * - * return length of name if success. - * return -1 if failure. - */ -int tox_get_name(const Tox *tox, int32_t friendnumber, uint8_t *name); - -/* returns the length of name on success. - * returns -1 on failure. - */ -int tox_get_name_size(const Tox *tox, int32_t friendnumber); -int tox_get_self_name_size(const Tox *tox); - -/* Set our user status. - * - * userstatus must be one of TOX_USERSTATUS values. - * max length of the status is TOX_MAX_STATUSMESSAGE_LENGTH. - * - * returns 0 on success. - * returns -1 on failure. - */ -int tox_set_status_message(Tox *tox, const uint8_t *status, uint16_t length); -int tox_set_user_status(Tox *tox, uint8_t userstatus); - -/* returns the length of status message on success. - * returns -1 on failure. - */ -int tox_get_status_message_size(const Tox *tox, int32_t friendnumber); -int tox_get_self_status_message_size(const Tox *tox); - -/* Copy friendnumber's status message into buf, truncating if size is over maxlen. - * Get the size you need to allocate from m_get_statusmessage_size. - * The self variant will copy our own status message. - * - * returns the length of the copied data on success - * retruns -1 on failure. - */ -int tox_get_status_message(const Tox *tox, int32_t friendnumber, uint8_t *buf, uint32_t maxlen); -int tox_get_self_status_message(const Tox *tox, uint8_t *buf, uint32_t maxlen); - -/* return one of TOX_USERSTATUS values. - * Values unknown to your application should be represented as TOX_USERSTATUS_NONE. - * As above, the self variant will return our own TOX_USERSTATUS. - * If friendnumber is invalid, this shall return TOX_USERSTATUS_INVALID. - */ -uint8_t tox_get_user_status(const Tox *tox, int32_t friendnumber); -uint8_t tox_get_self_user_status(const Tox *tox); - -/* returns timestamp of last time friendnumber was seen online, or 0 if never seen. - * returns -1 on error. - */ -uint64_t tox_get_last_online(const Tox *tox, int32_t friendnumber); - -/* Set our typing status for a friend. - * You are responsible for turning it on or off. - * - * returns 0 on success. - * returns -1 on failure. - */ -int tox_set_user_is_typing(Tox *tox, int32_t friendnumber, uint8_t is_typing); - -/* Get the typing status of a friend. - * - * returns 0 if friend is not typing. - * returns 1 if friend is typing. - */ -uint8_t tox_get_is_typing(const Tox *tox, int32_t friendnumber); - -/* Return the number of friends in the instance m. - * You should use this to determine how much memory to allocate - * for copy_friendlist. */ -uint32_t tox_count_friendlist(const Tox *tox); - -/* Return the number of online friends in the instance m. */ -uint32_t tox_get_num_online_friends(const Tox *tox); - -/* Copy a list of valid friend IDs into the array out_list. - * If out_list is NULL, returns 0. - * Otherwise, returns the number of elements copied. - * If the array was too small, the contents - * of out_list will be truncated to list_size. */ -uint32_t tox_get_friendlist(const Tox *tox, int32_t *out_list, uint32_t list_size); - -/* Set the function that will be executed when a friend request is received. - * Function format is function(Tox *tox, const uint8_t * public_key, const uint8_t * data, uint16_t length, void *userdata) - */ -void tox_callback_friend_request(Tox *tox, void (*function)(Tox *tox, const uint8_t *, const uint8_t *, uint16_t, - void *), void *userdata); - -/* Set the function that will be executed when a message from a friend is received. - * Function format is: function(Tox *tox, int32_t friendnumber, const uint8_t * message, uint16_t length, void *userdata) - */ -void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, 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(Tox *tox, int32_t friendnumber, const uint8_t * action, uint16_t length, void *userdata) - */ -void tox_callback_friend_action(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata); - -/* Set the callback for name changes. - * function(Tox *tox, int32_t friendnumber, const uint8_t *newname, uint16_t length, void *userdata) - * You are not responsible for freeing newname - */ -void tox_callback_name_change(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata); - -/* Set the callback for status message changes. - * function(Tox *tox, int32_t friendnumber, const uint8_t *newstatus, uint16_t length, void *userdata) - * You are not responsible for freeing newstatus. - */ -void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), - void *userdata); - -/* Set the callback for status type changes. - * function(Tox *tox, int32_t friendnumber, uint8_t TOX_USERSTATUS, void *userdata) - */ -void tox_callback_user_status(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata); - -/* Set the callback for typing changes. - * function (Tox *tox, int32_t friendnumber, uint8_t is_typing, void *userdata) - */ -void tox_callback_typing_change(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata); - -/* Set the callback for read receipts. - * function(Tox *tox, int32_t friendnumber, uint32_t receipt, void *userdata) - * - * If you are keeping a record of returns from m_sendmessage; - * receipt might be one of those values, meaning the message - * has been received on the other side. - * Since core doesn't track ids for you, receipt may not correspond to any message. - * In that case, you should discard it. - */ -void tox_callback_read_receipt(Tox *tox, void (*function)(Tox *tox, int32_t, uint32_t, void *), void *userdata); - -/* Set the callback for connection status changes. - * function(Tox *tox, int32_t friendnumber, uint8_t status, void *userdata) - * - * Status: - * 0 -- friend went offline after being previously online - * 1 -- friend went online - * - * NOTE: This callback is not called when adding friends, thus the "after - * being previously online" part. it's assumed that when adding friends, - * their connection status is offline. - */ -void tox_callback_connection_status(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata); - - -/**********ADVANCED FUNCTIONS (If you don't know what they do you can safely ignore them.) ************/ - -/* Functions to get/set the nospam part of the id. - */ -uint32_t tox_get_nospam(const Tox *tox); -void tox_set_nospam(Tox *tox, uint32_t nospam); - -/* Copy the public and secret key from the Tox object. - public_key and secret_key must be 32 bytes big. - if the pointer is NULL, no data will be copied to it.*/ -void tox_get_keys(Tox *tox, uint8_t *public_key, uint8_t *secret_key); - -/* Maximum size of custom packets. */ -#define TOX_MAX_CUSTOM_PACKET_SIZE 1373 - -/* Set handlers for custom lossy packets. - * Set the function to be called when friend sends us a lossy packet starting with byte. - * byte must be in the 200-254 range. - * - * NOTE: lossy packets behave like UDP packets meaning they might never reach the other side - * or might arrive more than once (if someone is messing with the connection) or might arrive - * in the wrong order. - * - * Unless latency is an issue, it is recommended that you use lossless packets instead. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_lossy_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), - void *object); - -/* Function to send custom lossy packets. - * First byte of data must be in the range: 200-254. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_send_lossy_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); - -/* Set handlers for custom lossless packets. - * Set the function to be called when friend sends us a lossless packet starting with byte. - * byte must be in the 160-191 range. - * - * Lossless packets behave kind of like TCP (reliability, arrive in order.) but with packets instead of a stream. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_lossless_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), - void *object); - -/* Function to send custom lossless packets. - * First byte of data must be in the range: 160-191. - * - * return -1 on failure. - * return 0 on success. - */ -int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); -/**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/ - -/* 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(). + * :: API version * - * 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) +/** + * The major version number. Incremented when the API or ABI changes in an + * incompatible way. */ -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) +#define TOX_VERSION_MAJOR 0u +/** + * The minor version number. Incremented when functionality is added without + * breaking the API or ABI. Set to 0 when the major version number is + * incremented. */ -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) +#define TOX_VERSION_MINOR 0u +/** + * The patch or revision number. Incremented when bugfixes are applied without + * changing any functionality or API or ABI. */ -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); +#define TOX_VERSION_PATCH 0u -/* Creates a new groupchat and puts it in the chats array. - * - * return group number on success. - * return -1 on failure. +/** + * A macro to check at preprocessing time whether the client code is compatible + * with the installed version of Tox. */ -int tox_add_groupchat(Tox *tox); +#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \ + (TOX_VERSION_MAJOR == MAJOR && \ + (TOX_VERSION_MINOR > MINOR || \ + (TOX_VERSION_MINOR == MINOR && \ + TOX_VERSION_PATCH >= PATCH))) -/* Delete a groupchat from the chats array. - * - * return 0 on success. - * return -1 if failure. +/** + * A macro to make compilation fail if the client code is not compatible with + * the installed version of Tox. */ -int tox_del_groupchat(Tox *tox, int groupnumber); +#define TOX_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \ + typedef char tox_required_version[TOX_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1] -/* 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 +/** + * Return the major version number of the library. Can be used to display the + * Tox library version or to check whether the client is compatible with the + * dynamically linked version of Tox. */ -int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key); +uint32_t tox_version_major(void); -/* invite friendnumber to groupnumber - * return 0 on success - * return -1 on failure +/** + * Return the minor version number of the library. */ -int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber); +uint32_t tox_version_minor(void); -/* 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); - -/****************AVATAR FUNCTIONS*****************/ - -/* 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 TOX_AVATAR_FORMAT) and 'hash' is the hash of - * the avatar data for caching purposes and it is exactly TOX_HASH_LENGTH long. If the image - * format is NONE, the hash is zeroed. - * +/** + * Return the patch number of the library. */ -void tox_callback_avatar_info(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, void *), - void *userdata); +uint32_t tox_version_patch(void); - -/* 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 TOX_AVATAR_FORMAT); 'hash' is the - * locally-calculated cryptographic hash of the avatar data and it is exactly - * TOX_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_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. +/** + * Return whether the compiled library version is compatible with the passed + * version numbers. */ -void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, - void *), void *userdata); +bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); -/* 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 TOX_AVATAR_FORMAT); - * data - pointer to the avatar data (may be NULL it the format is NONE); - * length - length of image data. Must be <= TOX_AVATAR_MAX_DATA_LENGTH. - * - * returns 0 on success - * returns -1 on failure. +/** + * A convenience macro to call tox_version_is_compatible with the currently + * compiling API version. */ -int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length); - -/* Unsets the user avatar. +#define TOX_VERSION_IS_ABI_COMPATIBLE() \ + tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH) - returns 0 on success (currently always returns 0) */ -int tox_unset_avatar(Tox *tox); -/* 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 TOX_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 TOX_HASH_LENGTH bytes long). + * :: Numeric constants * - * returns 0 on success; - * returns -1 on failure. - * - */ -int tox_get_self_avatar(const Tox *tox, 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 use is highly recommended to avoid unnecessary avatar - * updates. - * This function is a wrapper to internal message-digest functions. - * - * Arguments: - * hash - destination buffer for the hash data, it must be exactly TOX_HASH_LENGTH bytes long. - * data - data to be hashed; - * datalen - length of the data; for avatars, should be TOX_AVATAR_MAX_DATA_LENGTH - * - * returns 0 on success - * returns -1 on failure. +/** + * The size of a Tox Public Key in bytes. */ -int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen); +#define TOX_PUBLIC_KEY_SIZE 32 -/* 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'. +/** + * The size of a Tox address in bytes. Tox addresses are in the format + * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. * - * returns 0 on success - * returns -1 on failure. + * The checksum is computed over the Public Key and the nospam value. The first + * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an + * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam. */ -int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber); - +#define TOX_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) -/* 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. +/** + * Maximum length of a nickname in bytes. */ -int tox_send_avatar_info(Tox *tox, const int32_t friendnumber); +#define TOX_MAX_NAME_LENGTH 128 - -/* 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. +/** + * Maximum length of a status message in bytes. */ -int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber); +#define TOX_MAX_STATUS_MESSAGE_LENGTH 1007 -/****************FILE SENDING FUNCTIONS*****************/ -/* NOTE: This how to will be updated. - * - * HOW TO SEND FILES CORRECTLY: - * 1. Use tox_new_file_sender(...) to create a new file sender. - * 2. Wait for the callback set with tox_callback_file_control(...) to be called with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT - * 3. Send the data with tox_file_send_data(...) with chunk size tox_file_data_size(...) - * 4. When sending is done, send a tox_file_send_control(...) with send_receive = 0 and message_id = TOX_FILECONTROL_FINISHED - * 5. when the callback set with tox_callback_file_control(...) is called with receive_send == 1 and control_type == TOX_FILECONTROL_FINISHED - * the other person has received the file correctly. - * - * HOW TO RECEIVE FILES CORRECTLY: - * 1. wait for the callback set with tox_callback_file_send_request(...) - * 2. accept or refuse the connection with tox_file_send_control(...) with send_receive = 1 and message_id = TOX_FILECONTROL_ACCEPT or TOX_FILECONTROL_KILL - * 3. save all the data received with the callback set with tox_callback_file_data(...) to a file. - * 4. when the callback set with tox_callback_file_control(...) is called with receive_send == 0 and control_type == TOX_FILECONTROL_FINISHED - * the file is done transferring. - * 5. send a tox_file_send_control(...) with send_receive = 1 and message_id = TOX_FILECONTROL_FINISHED to confirm that we did receive the file. - * - * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. - * - * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) - * the receiver must send a control packet with send_receive == 1 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being - * a uint64_t (in host byte order) containing the number of bytes received. - * - * If the sender receives this packet, he must send a control packet with send_receive == 0 and control_type == TOX_FILECONTROL_ACCEPT - * then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet. - * - * To pause a file transfer send a control packet with control_type == TOX_FILECONTROL_PAUSE. - * To unpause a file transfer send a control packet with control_type == TOX_FILECONTROL_ACCEPT. - * - * If you receive a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_PAUSE, you must stop sending filenumber until the other - * person sends a control packet with send_receive == 0 and control_type == TOX_FILECONTROL_ACCEPT with the filenumber being a paused filenumber. - * - * If you receive a control packet with receive_send == 0 and control_type == TOX_FILECONTROL_PAUSE, it means the sender of filenumber has paused the - * transfer and will resume it later with a control packet with send_receive == 1 and control_type == TOX_FILECONTROL_ACCEPT for that file number. - * - * More to come... +/** + * Maximum length of a friend request message in bytes. */ +#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016 -enum { - TOX_FILECONTROL_ACCEPT, - TOX_FILECONTROL_PAUSE, - TOX_FILECONTROL_KILL, - TOX_FILECONTROL_FINISHED, - TOX_FILECONTROL_RESUME_BROKEN -}; -/* Set the callback for file send requests. - * - * Function(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length, void *userdata) +/** + * Maximum length of a single message after which it should be split. */ -void tox_callback_file_send_request(Tox *tox, void (*function)(Tox *m, int32_t, uint8_t, uint64_t, const uint8_t *, - uint16_t, void *), void *userdata); +#define TOX_MAX_MESSAGE_LENGTH 1368 -/* Set the callback for file control requests. - * - * receive_send is 1 if the message is for a slot on which we are currently sending a file and 0 if the message - * is for a slot on which we are receiving the file - * - * Function(Tox *tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) - * +/** + * Maximum size of custom packets. TODO: should be LENGTH? */ -void tox_callback_file_control(Tox *tox, void (*function)(Tox *m, int32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, - uint16_t, void *), void *userdata); +#define TOX_MAX_CUSTOM_PACKET_SIZE 1373 -/* Set the callback for file data. - * - * Function(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata) - * - */ -void tox_callback_file_data(Tox *tox, void (*function)(Tox *m, int32_t, uint8_t, const uint8_t *, uint16_t length, - void *), void *userdata); - - -/* Send a file send request. - * Maximum filename length is 255 bytes. - * return file number on success - * return -1 on failure +/** + * The number of bytes in a hash generated by tox_hash. */ -int tox_new_file_sender(Tox *tox, int32_t friendnumber, uint64_t filesize, const uint8_t *filename, - uint16_t filename_length); +#define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 -/* Send a file control request. - * - * send_receive is 0 if we want the control packet to target a file we are currently sending, - * 1 if it targets a file we are currently receiving. +/******************************************************************************* * - * return 0 on success - * return -1 on failure - */ -int tox_file_send_control(Tox *tox, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, - const uint8_t *data, uint16_t length); - -/* Send file data. + * :: Global enumerations * - * return 0 on success - * return -1 on failure - */ -int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length); + ******************************************************************************/ -/* Returns the recommended/maximum size of the filedata you send with tox_file_send_data() - * - * return size on success - * return -1 on failure (currently will never return -1) - */ -int tox_file_data_size(const Tox *tox, int32_t friendnumber); -/* Give the number of bytes left to be sent/received. - * - * send_receive is 0 if we want the sending files, 1 if we want the receiving. - * - * return number of bytes remaining to be sent/received on success - * return 0 on failure +/** + * Represents the possible statuses a client can have. */ -uint64_t tox_file_data_remaining(const Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive); +typedef enum TOX_STATUS { + /** + * User is online and available. + */ + TOX_STATUS_NONE, + /** + * User is away. Clients can set this e.g. after a user defined + * inactivity time. + */ + TOX_STATUS_AWAY, + /** + * User is busy. Signals to other clients that this client does not + * currently wish to communicate. + */ + TOX_STATUS_BUSY +} TOX_STATUS; -/***************END OF FILE SENDING FUNCTIONS******************/ -/* - * Use this function to bootstrap the client. - */ - -/* Resolves address into an IP address. If successful, sends a "get nodes" - * request to the given node with ip, port (in host byte order). - * and public_key to setup connections - * - * address can be a hostname or an IP address (IPv4 or IPv6). +/******************************************************************************* * - * returns 1 if the address could be converted into an IP address - * returns 0 otherwise - */ -int tox_bootstrap_from_address(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key); - -/* Like tox_bootstrap_from_address but for TCP relays only. + * :: Startup options * - * return 0 on failure. - * return 1 on success. - */ -int tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key); + ******************************************************************************/ -/* return 0 if we are not connected to the DHT. - * return 1 if we are. - */ -int tox_isconnected(const Tox *tox); -typedef enum { - TOX_PROXY_NONE, - TOX_PROXY_SOCKS5, - TOX_PROXY_HTTP +typedef enum TOX_PROXY_TYPE { + /** + * Don't use a proxy. + */ + TOX_PROXY_TYPE_NONE, + /** + * HTTP proxy using CONNECT. + */ + TOX_PROXY_TYPE_HTTP, + /** + * SOCKS proxy for simple socket pipes. + */ + TOX_PROXY_TYPE_SOCKS5 } TOX_PROXY_TYPE; -typedef struct { - /* - * The type of UDP socket created depends on ipv6enabled: - * If set to 0 (zero), creates an IPv4 socket which subsequently only allows - * IPv4 communication - * If set to anything else (default), creates an IPv6 socket which allows both IPv4 AND - * IPv6 communication - */ - uint8_t ipv6enabled; - /* Set to 1 to disable udp support. (default: 0) - This will force Tox to use TCP only which may slow things down. - Disabling udp support is necessary when using proxies or Tor.*/ - uint8_t udp_disabled; - uint8_t proxy_type; /* a value from TOX_PROXY_TYPE */ - char proxy_address[256]; /* Proxy ip or domain in NULL terminated string format. */ - uint16_t proxy_port; /* Proxy port in host byte order. */ -} Tox_Options; - -/* - * Run this function at startup. - * - * Options are some options that can be passed to the Tox instance (see above struct). - * - * If options is NULL, tox_new() will use default settings. - * - * Initializes a tox structure - * return allocated instance of tox on success. - * return NULL on failure. +/** + * This struct contains all the startup options for Tox. You can either allocate + * this object yourself, and pass it to tox_options_default, or call + * tox_options_new to get a new default options object. */ -Tox *tox_new(Tox_Options *options); +struct Tox_Options { + /** + * The type of socket to create. + * + * If this is set to false, an IPv4 socket is created, which subsequently + * only allows IPv4 communication. + * If it is set to true, an IPv6 socket is created, allowing both IPv4 and + * IPv6 communication. + */ + bool ipv6_enabled; -/* Run this before closing shop. - * Free all datastructures. */ + /** + * Enable the use of UDP communication when available. + * + * Setting this to false will force Tox to use TCP only. Communications will + * need to be relayed through a TCP relay node, potentially slowing them down. + * Disabling UDP support is necessary when using anonymous proxies or Tor. + */ + bool udp_enabled; + + /** + * Pass communications through a proxy. + */ + TOX_PROXY_TYPE proxy_type; + + /** + * The IP address or DNS name of the proxy to be used. + * + * If used, this must be non-NULL and be a valid DNS name. The name must not + * exceed 255 characters, and be in a NUL-terminated C string format + * (255 chars + 1 NUL byte). + * + * This member is ignored (it can be NULL) if proxy_enabled is false. + */ + char const *proxy_address; + + /** + * The port to use to connect to the proxy server. + * + * Ports must be in the range (1, 65535). The value is ignored if + * proxy_enabled is false. + */ + uint16_t proxy_port; +}; + + +/** + * Initialises a Tox_Options object with the default options. + * + * The result of this function is independent of the original options. All + * values will be overwritten, no values will be read (so it is permissible + * to pass an uninitialised object). + * + * If options is NULL, this function has no effect. + * + * @param options An options object to be filled with default options. + */ +void tox_options_default(struct Tox_Options *options); + + +typedef enum TOX_ERR_OPTIONS_NEW { + TOX_ERR_OPTIONS_NEW_OK, + /** + * The function failed to allocate enough memory for the options struct. + */ + TOX_ERR_OPTIONS_NEW_MALLOC +} TOX_ERR_OPTIONS_NEW; + +/** + * Allocates a new Tox_Options object and initialises it with the default + * options. This function can be used to preserve long term ABI compatibility by + * giving the responsibility of allocation and deallocation to the Tox library. + * + * Objects returned from this function must be freed using the tox_options_free + * function. + * + * @return A new Tox_Options object with default options or NULL on failure. + */ +struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error); + + +/** + * Releases all resources associated with an options objects. + * + * Passing a pointer that was not returned by tox_options_new results in + * undefined behaviour. + */ +void tox_options_free(struct Tox_Options *options); + + +/******************************************************************************* + * + * :: Creation and destruction + * + ******************************************************************************/ + + +typedef enum TOX_ERR_NEW { + TOX_ERR_NEW_OK, + TOX_ERR_NEW_NULL, + /** + * The function was unable to allocate enough memory to store the internal + * structures for the Tox object. + */ + TOX_ERR_NEW_MALLOC, + /** + * The function was unable to bind to a port. This may mean that all ports + * have already been bound, e.g. by other Tox instances, or it may mean + * a permission error. You may be able to gather more information from errno. + */ + TOX_ERR_NEW_PORT_ALLOC, + /** + * proxy_enabled was true, but the proxy_address passed had an invalid format + * or was NULL. + */ + TOX_ERR_NEW_PROXY_BAD_HOST, + /** + * proxy_enabled was true, but the proxy_port was invalid. + */ + TOX_ERR_NEW_PROXY_BAD_PORT, + /** + * The proxy address passed could not be resolved. + */ + TOX_ERR_NEW_PROXY_NOT_FOUND, + /** + * The byte array to be loaded contained an encrypted save. + */ + TOX_ERR_NEW_LOAD_ENCRYPTED, + /** + * The data format was invalid. This can happen when loading data that was + * saved by an older version of Tox, or when the data has been corrupted. + * When loading from badly formatted data, some data may have been loaded, + * and the rest is discarded. Passing an invalid length parameter also + * causes this error. + */ + TOX_ERR_NEW_LOAD_BAD_FORMAT +} TOX_ERR_NEW; + + +/** + * @brief Creates and initialises a new Tox instance with the options passed. + * + * This function will bring the instance into a valid state. Running the event + * loop with a new instance will operate correctly. + * + * If the data parameter is not NULL, this function will load the Tox instance + * from a byte array previously filled by tox_save. + * + * If loading failed or succeeded only partially, the new or partially loaded + * instance is returned and an error code is set. + * + * @param options An options object as described above. If this parameter is + * NULL, the default options are used. + * @param data A byte array containing data previously stored by tox_save. + * @param length The length of the byte array data. If this parameter is 0, the + * data parameter is ignored. + * + * @see tox_iteration for the event loop. + */ +Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t length, TOX_ERR_NEW *error); + + +/** + * Releases all resources associated with the Tox instance and disconnects from + * the network. + * + * After calling this function, the Tox pointer becomes invalid. No other + * functions can be called, and the pointer value can no longer be read. + */ void tox_kill(Tox *tox); -/* Return the time in milliseconds before tox_do() should be called again + +/** + * Calculates the number of bytes required to store the tox instance with + * tox_save. This function cannot fail. The result is always greater than 0. + * + * @see threading for concurrency implications. + */ +size_t tox_save_size(Tox const *tox); + +/** + * Store all information associated with the tox instance to a byte array. + * + * @param data A memory region large enough to store the tox instance data. + * Call tox_save_size to find the number of bytes required. If this parameter + * is NULL, this function has no effect. + */ +void tox_save(Tox const *tox, uint8_t *data); + + +/******************************************************************************* + * + * :: Connection lifecycle and event loop + * + ******************************************************************************/ + + +typedef enum TOX_ERR_BOOTSTRAP { + TOX_ERR_BOOTSTRAP_OK, + TOX_ERR_BOOTSTRAP_NULL, + /** + * The address could not be resolved to an IP address, or the IP address + * passed was invalid. + */ + TOX_ERR_BOOTSTRAP_BAD_ADDRESS, + /** + * The port passed was invalid. The valid port range is (1, 65535). + */ + TOX_ERR_BOOTSTRAP_BAD_PORT +} TOX_ERR_BOOTSTRAP; + +/** + * Sends a "get nodes" request to the given bootstrap node with IP, port, and + * public key to setup connections. + * + * This function will attempt to connect to the node using UDP and TCP at the + * same time. + * + * Tox will use the node as a TCP relay in case Tox_Options.udp_enabled was + * false, and also to connect to friends that are in TCP-only mode. Tox will + * also use the TCP connection when NAT hole punching is slow, and later switch + * to UDP if hole punching succeeds. + * + * @param address The hostname or IP address (IPv4 or IPv6) of the node. + * @param port The port on the host on which the bootstrap Tox instance is + * listening. + * @param public_key The long term public key of the bootstrap node + * (TOX_PUBLIC_KEY_SIZE bytes). + * @return true on success. + */ +bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error); + + +/** + * Adds additional host:port pair as TCP relay. + * + * This function can be used to initiate TCP connections to different ports on + * the same bootstrap node, or to add TCP relays without using them as + * bootstrap nodes. + * + * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay. + * @param port The port on the host on which the TCP relay is listening. + * @param public_key The long term public key of the TCP relay + * (TOX_PUBLIC_KEY_SIZE bytes). + * @return true on success. + */ +bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, + TOX_ERR_BOOTSTRAP *error); + + +typedef enum TOX_CONNECTION { + /** + * There is no connection. This instance, or the friend the state change is + * about, is now offline. + */ + TOX_CONNECTION_NONE, + /** + * A TCP connection has been established. For the own instance, this means it + * is connected through a TCP relay, only. For a friend, this means that the + * connection to that particular friend goes through a TCP relay. + */ + TOX_CONNECTION_TCP4, + TOX_CONNECTION_TCP6, + /** + * A UDP connection has been established. For the own instance, this means it + * is able to send UDP packets to DHT nodes, but may still be connected to + * a TCP relay. For a friend, this means that the connection to that + * particular friend was built using direct UDP packets. + */ + TOX_CONNECTION_UDP4, + TOX_CONNECTION_UDP6 +} TOX_CONNECTION; + + +/** + * Return whether we are connected to the DHT. The return value is equal to the + * last value received through the `connection_status` callback. + */ +TOX_CONNECTION tox_get_connection_status(Tox const *tox); + +/** + * The function type for the `connection_status` callback. + * + * @param connection_status Equal to the return value of + * tox_get_connection_status. + */ +typedef void tox_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data); + +/** + * Set the callback for the `connection_status` event. Pass NULL to unset. + * + * This event is triggered whenever there is a change in the DHT connection + * state. When disconnected, a client may choose to call tox_bootstrap again, to + * reconnect to the DHT. Note that this state may frequently change for short + * amounts of time. Clients should therefore not immediately bootstrap on + * receiving a disconnect. + * + * TODO: how long should a client wait before bootstrapping again? + */ +void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function, void *user_data); + + +/** + * Return the time in milliseconds before tox_iteration() should be called again * for optimal performance. - * - * returns time (in ms) before the next tox_do() needs to be run on success. */ -uint32_t tox_do_interval(Tox *tox); +uint32_t tox_iteration_interval(Tox const *tox); -/* The main loop that needs to be run in intervals of tox_do_interval() ms. */ -void tox_do(Tox *tox); -/* SAVING AND LOADING FUNCTIONS: */ - -/* return size of messenger data (for saving). */ -uint32_t tox_size(const Tox *tox); - -/* Save the messenger in data (must be allocated memory of size Messenger_size()). */ -void tox_save(const Tox *tox, uint8_t *data); - -/* Load the messenger from data of size length. - * NOTE: The Tox save format isn't stable yet meaning this function sometimes - * returns -1 when loading older saves. This however does not mean nothing was - * loaded from the save. - * - * returns 0 on success - * returns -1 on failure - * returns +1 on finding encrypted save data +/** + * The main loop that needs to be run in intervals of tox_iteration_interval() + * milliseconds. */ -int tox_load(Tox *tox, const uint8_t *data, uint32_t length); +void tox_iteration(Tox *tox); + + +/******************************************************************************* + * + * :: Internal client information (Tox address/id) + * + ******************************************************************************/ + + +/** + * Writes the Tox friend address of the client to a byte array. The address is + * not in human-readable format. If a client wants to display the address, + * formatting is required. + * + * @param address A memory region of at least TOX_ADDRESS_SIZE bytes. If this + * parameter is NULL, this function has no effect. + * @see TOX_ADDRESS_SIZE for the address format. + */ +void tox_self_get_address(Tox const *tox, uint8_t *address); + + +/** + * Set the 4-byte nospam part of the address. + * + * @param nospam Any 32 bit unsigned integer. + */ +void tox_self_set_nospam(Tox *tox, uint32_t nospam); + +/** + * Get the 4-byte nospam part of the address. + */ +uint32_t tox_self_get_nospam(Tox const *tox); + +/** + * Copy the Tox Public Key (long term public key) from the Tox object. + * + * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If + * this parameter is NULL, this function has no effect. + */ +void tox_self_get_public_key(Tox const *tox, uint8_t *public_key); + +/** + * Copy the private key from the Tox object. + * + * @param private_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If + * this parameter is NULL, this function has no effect. + */ +void tox_self_get_private_key(Tox const *tox, uint8_t *private_key); + + +/******************************************************************************* + * + * :: User-visible client information (nickname/status) + * + ******************************************************************************/ + + +/** + * Common error codes for all functions that set a piece of user-visible + * client information. + */ +typedef enum TOX_ERR_SET_INFO { + TOX_ERR_SET_INFO_OK, + TOX_ERR_SET_INFO_NULL, + /** + * Information length exceeded maximum permissible size. + */ + TOX_ERR_SET_INFO_TOO_LONG +} TOX_ERR_SET_INFO; + + +/** + * Set the nickname for the Tox client. + * + * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is 0, the name + * parameter is ignored (it can be NULL), and the nickname is set back to empty. + * + * @param name A byte array containing the new nickname. + * @param length The size of the name byte array. + * + * @return true on success. + */ +bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET_INFO *error); + +/** + * Return the length of the current nickname as passed to tox_self_set_name. + * + * If no nickname was set before calling this function, the name is empty, + * and this function returns 0. + * + * @see threading for concurrency implications. + */ +size_t tox_self_get_name_size(Tox const *tox); + +/** + * Write the nickname set by tox_self_set_name to a byte array. + * + * If no nickname was set before calling this function, the name is empty, + * and this function has no effect. + * + * Call tox_self_get_name_size to find out how much memory to allocate for + * the result. + * + * @param name A valid memory location large enough to hold the nickname. + * If this parameter is NULL, the function has no effect. + */ +void tox_self_get_name(Tox const *tox, uint8_t *name); + + +/** + * Set the client's status message. + * + * Status message length cannot exceed TOX_MAX_STATUS_MESSAGE_LENGTH. If + * length is 0, the status parameter is ignored (it can be NULL), and the + * user status is set back to empty. + */ +bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, TOX_ERR_SET_INFO *error); + +/** + * Return the length of the current status message as passed to + * tox_self_set_status_message. + * + * If no status message was set before calling this function, the status + * is empty, and this function returns 0. + * + * @see threading for concurrency implications. + */ +size_t tox_self_get_status_message_size(Tox const *tox); + +/** + * Write the status message set by tox_self_set_status_message to a byte array. + * + * If no status message was set before calling this function, the status is + * empty, and this function has no effect. + * + * Call tox_self_status_message_size to find out how much memory to allocate for + * the result. + * + * @param name A valid memory location large enough to hold the status message. + * If this parameter is NULL, the function has no effect. + */ +void tox_self_get_status_message(Tox const *tox, uint8_t *status); + + +/** + * Set the client's user status. + * + * @param user_status One of the user statuses listed in the enumeration above. + */ +void tox_self_set_status(Tox *tox, TOX_STATUS user_status); + +/** + * Returns the client's user status. + */ +TOX_STATUS tox_self_get_status(Tox const *tox); + + +/******************************************************************************* + * + * :: Friend list management + * + ******************************************************************************/ + + +typedef enum TOX_ERR_FRIEND_ADD { + TOX_ERR_FRIEND_ADD_OK, + TOX_ERR_FRIEND_ADD_NULL, + /** + * The length of the friend request message exceeded + * TOX_MAX_FRIEND_REQUEST_LENGTH. + */ + TOX_ERR_FRIEND_ADD_TOO_LONG, + /** + * The friend request message was empty. This, and the TOO_LONG code will + * never be returned from tox_friend_add_norequest. + */ + TOX_ERR_FRIEND_ADD_NO_MESSAGE, + /** + * The friend address belongs to the sending client. + */ + TOX_ERR_FRIEND_ADD_OWN_KEY, + /** + * A friend request has already been sent, or the address belongs to a friend + * that is already on the friend list. + */ + TOX_ERR_FRIEND_ADD_ALREADY_SENT, + /** + * The friend address checksum failed. + */ + TOX_ERR_FRIEND_ADD_BAD_CHECKSUM, + /** + * The friend was already there, but the nospam value was different. + */ + TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM, + /** + * A memory allocation failed when trying to increase the friend list size. + */ + TOX_ERR_FRIEND_ADD_MALLOC +} TOX_ERR_FRIEND_ADD; + +/** + * Add a friend to the friend list and send a friend request. + * + * A friend request message must be at least 1 byte long and at most + * TOX_MAX_FRIEND_REQUEST_LENGTH. + * + * Friend numbers are unique identifiers used in all functions that operate on + * friends. Once added, a friend number is stable for the lifetime of the Tox + * object. After saving the state and reloading it, the friend numbers may not + * be the same as before. Deleting a friend creates a gap in the friend number + * set, which is filled by the next adding of a friend. + * + * If more than UINT32_MAX friends are added, this function causes undefined + * behaviour. + * + * @param address The address of the friend (returned by tox_self_get_address of + * the friend you wish to add) it must be TOX_ADDRESS_SIZE bytes. + * @param message The message that will be sent along with the friend request. + * @param length The length of the data byte array. + * + * @return the friend number. + */ +uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message, size_t length, + TOX_ERR_FRIEND_ADD *error); + + +/** + * Add a friend without sending a friend request. + * + * This function is used to add a friend in response to a friend request. If the + * client receives a friend request, it can be reasonably sure that the other + * client added this client as a friend, eliminating the need for a friend + * request. + * + * This function is also useful in a situation where both instances are + * controlled by the same entity, so that this entity can perform the mutual + * friend adding. In this case, there is no need for a friend request, either. + * + * @param public_key A byte array of length TOX_PUBLIC_KEY_SIZE containing the + * Public Key (not the Address) of the friend to add. + * + * @return the friend number. + * @see tox_friend_add for a more detailed description of friend numbers. + */ +uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error); + + +typedef enum TOX_ERR_FRIEND_DELETE { + TOX_ERR_FRIEND_DELETE_OK, + /** + * There was no friend with the given friend number. No friends were deleted. + */ + TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND +} TOX_ERR_FRIEND_DELETE; + +/** + * Remove a friend from the friend list. + * + * This does not notify the friend of their deletion. After calling this + * function, this client will appear offline to the friend and no communication + * can occur between the two. + * + * @friend_number Friend number for the friend to be deleted. + * + * @return true on success. + */ +bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error); + + +/******************************************************************************* + * + * :: Friend list queries + * + ******************************************************************************/ + + +typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { + TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK, + TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL, + /** + * No friend with the given Public Key exists on the friend list. + */ + TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND +} TOX_ERR_FRIEND_BY_PUBLIC_KEY; + +/** + * Return the friend number associated with that Public Key. + * + * @param public_key A byte array containing the Public Key. + */ +uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); + + +typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { + TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, + /** + * No friend with the given number exists on the friend list. + */ + TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND +} TOX_ERR_FRIEND_GET_PUBLIC_KEY; + +/** + * Copies the Public Key associated with a given friend number to a byte array. + * + * @param friend_number The friend number you want the Public Key of. + * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If + * this parameter is NULL, this function has no effect. + * + * @return true on success. + */ +bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t *public_key, + TOX_ERR_FRIEND_GET_PUBLIC_KEY *error); + + +/** + * Checks if a friend with the given friend number exists and returns true if + * it does. + */ +bool tox_friend_exists(Tox const *tox, uint32_t friend_number); + + +/** + * Return the number of friends on the friend list. + * + * This function can be used to determine how much memory to allocate for + * tox_friend_list. + */ +size_t tox_friend_list_size(Tox const *tox); + + +/** + * Copy a list of valid friend numbers into an array. + * + * Call tox_friend_list_size to determine the number of elements to allocate. + * + * @param list A memory region with enough space to hold the friend list. If + * this parameter is NULL, this function has no effect. + */ +void tox_friend_list(Tox const *tox, uint32_t *list); + + + +/******************************************************************************* + * + * :: Friend-specific state queries (can also be received through callbacks) + * + ******************************************************************************/ + + +/** + * Common error codes for friend state query functions. + */ +typedef enum TOX_ERR_FRIEND_QUERY { + TOX_ERR_FRIEND_QUERY_OK, + /** + * The pointer parameter for storing the query result (name, message) was + * NULL. Unlike the `_self_` variants of these functions, which have no effect + * when a parameter is NULL, these functions return an error in that case. + */ + TOX_ERR_FRIEND_QUERY_NULL, + /** + * The friend_number did not designate a valid friend. + */ + TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND +} TOX_ERR_FRIEND_QUERY; + + +/** + * Return the length of the friend's name. If the friend number is invalid, the + * return value is unspecified. + * + * The return value is equal to the `length` argument received by the last + * `friend_name` callback. + */ +size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); + +/** + * Write the name of the friend designated by the given friend number to a byte + * array. + * + * Call tox_friend_get_name_size to determine the allocation size for the `name` + * parameter. + * + * The data written to `name` is equal to the data received by the last + * `friend_name` callback. + * + * @param name A valid memory region large enough to store the friend's name. + * + * @return true on success. + */ +bool tox_friend_get_name(Tox const *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error); + +/** + * The function type for the `friend_name` callback. + * + * @param friend_number The friend number of the friend whose name changed. + * @param name A byte array containing the same data as + * tox_friend_get_name would write to its `name` parameter. + * @param length A value equal to the return value of + * tox_friend_get_name_size. + */ +typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, uint8_t const *name, size_t length, void *user_data); + +/** + * Set the callback for the `friend_name` event. Pass NULL to unset. + * + * This event is triggered when a friend changes their name. + */ +void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data); + + +/** + * Return the length of the friend's status message. If the friend number is + * invalid, the return value is unspecified. + */ +size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); + +/** + * Write the name of the friend designated by the given friend number to a byte + * array. + * + * Call tox_friend_get_name_size to determine the allocation size for the `name` + * parameter. + * + * The data written to `message` is equal to the data received by the last + * `friend_status_message` callback. + * + * @param name A valid memory region large enough to store the friend's name. + */ +bool tox_friend_get_status_message(Tox const *tox, uint32_t friend_number, uint8_t *message, + TOX_ERR_FRIEND_QUERY *error); + +/** + * The function type for the `friend_status_message` callback. + * + * @param friend_number The friend number of the friend whose status message + * changed. + * @param message A byte array containing the same data as + * tox_friend_get_status_message would write to its `message` parameter. + * @param length A value equal to the return value of + * tox_friend_get_status_message_size. + */ +typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, uint8_t const *message, size_t length, + void *user_data); + +/** + * Set the callback for the `friend_status_message` event. Pass NULL to unset. + * + * This event is triggered when a friend changes their name. + */ +void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data); + + +/** + * Return the friend's user status (away/busy/...). If the friend number is + * invalid, the return value is unspecified. + * + * The status returned is equal to the last status received through the + * `friend_status` callback. + */ +TOX_STATUS tox_friend_get_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); + +/** + * The function type for the `friend_status` callback. + * + * @param friend_number The friend number of the friend whose user status + * changed. + * @param status The new user status. + */ +typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_STATUS status, void *user_data); + +/** + * Set the callback for the `friend_status` event. Pass NULL to unset. + * + * This event is triggered when a friend changes their user status. + */ +void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void *user_data); + + +/** + * Check whether a friend is currently connected to this client. + * + * The result of this function is equal to the last value received by the + * `friend_connection_status` callback. + * + * @param friend_number The friend number for which to query the connection + * status. + * + * @return the friend's connection status as it was received through the + * `friend_connection_status` event. + */ +TOX_CONNECTION tox_friend_get_connection_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); + +/** + * The function type for the `friend_connection_status` callback. + * + * @param friend_number The friend number of the friend whose connection status + * changed. + * @param connection_status The result of calling + * tox_friend_get_connection_status on the passed friend_number. + */ +typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, + void *user_data); + +/** + * Set the callback for the `friend_connection_status` event. Pass NULL to + * unset. + * + * This event is triggered when a friend goes offline after having been online, + * or when a friend goes online. + * + * This callback is not called when adding friends. It is assumed that when + * adding friends, their connection status is offline. + */ +void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function, void *user_data); + + +/** + * Check whether a friend is currently typing a message. + * + * @param friend_number The friend number for which to query the typing status. + * + * @return true if the friend is typing. + * @return false if the friend is not typing, or the friend number was + * invalid. Inspect the error code to determine which case it is. + */ +bool tox_friend_get_typing(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); + +/** + * The function type for the `friend_typing` callback. + * + * @param friend_number The friend number of the friend who started or stopped + * typing. + * @param is_typing The result of calling tox_friend_get_typing on the passed + * friend_number. + */ +typedef void tox_friend_typing_cb(Tox *tox, uint32_t friend_number, bool is_typing, void *user_data); + +/** + * Set the callback for the `friend_typing` event. Pass NULL to unset. + * + * This event is triggered when a friend starts or stops typing. + */ +void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void *user_data); + + +/******************************************************************************* + * + * :: Sending private messages + * + ******************************************************************************/ + + +typedef enum TOX_ERR_SET_TYPING { + TOX_ERR_SET_TYPING_OK, + /** + * The friend number did not designate a valid friend. + */ + TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND +} TOX_ERR_SET_TYPING; + +/** + * Set the client's typing status for a friend. + * + * The client is responsible for turning it on or off. + * + * @param friend_number The friend to which the client is typing a message. + * @param is_typing The typing status. True means the client is typing. + * + * @return true on success. + */ +bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error); + + +typedef enum TOX_ERR_SEND_MESSAGE { + TOX_ERR_SEND_MESSAGE_OK, + TOX_ERR_SEND_MESSAGE_NULL, + /** + * The friend number did not designate a valid friend. + */ + TOX_ERR_SEND_MESSAGE_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_SEND_MESSAGE_FRIEND_NOT_CONNECTED, + /** + * An allocation error occurred while increasing the send queue size. + */ + TOX_ERR_SEND_MESSAGE_SENDQ, + /** + * Message length exceeded TOX_MAX_MESSAGE_LENGTH. + */ + TOX_ERR_SEND_MESSAGE_TOO_LONG, + /** + * Attempted to send a zero-length message. + */ + TOX_ERR_SEND_MESSAGE_EMPTY +} TOX_ERR_SEND_MESSAGE; + +/** + * Send a text chat message to an online friend. + * + * This function creates a chat message packet and pushes it into the send + * queue. + * + * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages + * must be split by the client and sent as separate messages. Other clients can + * then reassemble the fragments. Messages may not be empty. + * + * The return value of this function is the message ID. If a read receipt is + * received, the triggered `read_receipt` event will be passed this message ID. + * + * Message IDs are unique per friend. The first message ID is 0. Message IDs are + * incremented by 1 each time a message is sent. If UINT32_MAX messages were + * sent, the next message ID is 0. + */ +uint32_t tox_send_message(Tox *tox, uint32_t friend_number, uint8_t const *message, size_t length, + TOX_ERR_SEND_MESSAGE *error); + + +/** + * Send an action to an online friend. + * + * This is similar to /me (CTCP ACTION) on IRC. + * + * Message ID space is shared between tox_send_message and tox_send_action. This + * means that sending a message will cause the next message ID from sending an + * action will be incremented. + * + * @see tox_send_message for more details. + */ +uint32_t tox_send_action(Tox *tox, uint32_t friend_number, uint8_t const *action, size_t length, + TOX_ERR_SEND_MESSAGE *error); + + +/** + * The function type for the `read_receipt` callback. + * + * @param friend_number The friend number of the friend who received the message. + * @param message_id The message ID as returned from tox_send_message or + * tox_send_action corresponding to the message sent. + */ +typedef void tox_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data); + +/** + * Set the callback for the `read_receipt` event. Pass NULL to unset. + * + * This event is triggered when a read receipt is received from a friend. This + * normally means that the message has been received by the friend, however a + * friend can send a read receipt with any message ID in it, so the number + * received here may not correspond to any message sent through tox_send_message + * or tox_send_action. In that case, the receipt should be discarded. + */ +void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *user_data); + + +/******************************************************************************* + * + * :: Receiving private messages and friend requests + * + ******************************************************************************/ + + +/** + * The function type for the `friend_request` callback. + * + * @param public_key The Public Key of the user who sent the friend request. + * @param time_delta A delta in seconds between when the message was composed + * and when it is being transmitted. For messages that are sent immediately, + * it will be 0. If a message was written and couldn't be sent immediately + * (due to a connection failure, for example), the time_delta is an + * approximation of when it was composed. + * @param message The message they sent along with the request. + * @param length The size of the message byte array. + */ +typedef void tox_friend_request_cb(Tox *tox, uint8_t const *public_key, /*uint32_t time_delta, */uint8_t const *message, + size_t length, void *user_data); + +/** + * Set the callback for the `friend_request` event. Pass NULL to unset. + * + * This event is triggered when a friend request is received. + */ +void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void *user_data); + + +/** + * The function type for the `friend_message` callback. + * + * @param friend_number The friend number of the friend who sent the message. + * @param time_delta Time between composition and sending. + * @param message The message data they sent. + * @param length The size of the message byte array. + * + * @see tox_friend_request_cb for more information on time_delta. + */ +typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */uint8_t const *message, + size_t length, void *user_data); + +/** + * Set the callback for the `friend_message` event. Pass NULL to unset. + * + * This event is triggered when a message from a friend is received. + */ +void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data); + + +/** + * The function type for the `friend_action` callback. + * + * @param friend_number The friend number of the friend who sent the action. + * @param time_delta Time between composition and sending. + * @param action The action message data they sent. + * @param length The size of the action byte array. + * + * @see tox_friend_request_cb for more information on time_delta. + */ +typedef void tox_friend_action_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */uint8_t const *action, + size_t length, void *user_data); + +/** + * Set the callback for the `friend_action` event. Pass NULL to unset. + * + * This event is triggered when an action from a friend is received. + */ +void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void *user_data); + + + +/******************************************************************************* + * + * :: File transmission: common between sending and receiving + * + ******************************************************************************/ + + +typedef enum TOX_FILE_KIND { + /** + * Arbitrary file data. Clients can choose to handle it based on the file name + * or magic or any other way they choose. + */ + TOX_FILE_KIND_DATA, + /** + * Avatar data. This consists of tox_hash(image) + image. + * + * Avatars can be sent at any time the client wishes. Generally, a client will + * send the avatar to a friend when that friend comes online, and to all + * friends when the avatar changed. A client can save some traffic by + * remembering which friend received the updated avatar already and only send + * it if the friend has an out of date avatar. + * + * Clients who receive avatar send requests can reject it (by sending + * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by + * sending TOX_FILE_CONTROL_RESUME). The first chunk will contain the hash in + * its first TOX_HASH_LENGTH bytes. A client can compare this hash with a + * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar + * transfer if it matches. + */ + TOX_FILE_KIND_AVATAR +} TOX_FILE_KIND; + + +/** + * 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 use is highly recommended to + * avoid unnecessary avatar updates. + * + * If length is zero or data is NULL, the hash will contain all zero. If hash is + * NULL, the function returns false, otherwise it returns true. + * + * This function is a wrapper to internal message-digest functions. + * + * @param hash A valid memory location the hash data. It must be at least + * TOX_HASH_LENGTH bytes in size. + * @param data Data to be hashed or NULL. + * @param length Size of the data array or 0. + * + * @return true if hash was not NULL. + */ +bool tox_hash(uint8_t *hash, uint8_t const *data, size_t length); + + +typedef enum TOX_FILE_CONTROL { + /** + * Sent by the receiving side to accept a file send request. Also sent after a + * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving. + */ + TOX_FILE_CONTROL_RESUME, + /** + * Sent by clients to pause the file transfer. The initial state of a file + * transfer is always paused on the receiving side and running on the sending + * side. If both the sending and receiving side pause the transfer, then both + * need to send TOX_FILE_CONTROL_RESUME for the transfer to resume. + */ + TOX_FILE_CONTROL_PAUSE, + /** + * Sent by the receiving side to reject a file send request before any other + * commands are sent. Also sent by either side to terminate a file transfer. + */ + TOX_FILE_CONTROL_CANCEL +} TOX_FILE_CONTROL; + + +typedef enum TOX_ERR_FILE_CONTROL { + TOX_ERR_FILE_CONTROL_OK, + /** + * The friend_number passed did not designate a valid friend. + */ + TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED, + /** + * No file transfer with the given file number was found for the given friend. + */ + TOX_ERR_FILE_CONTROL_NOT_FOUND, + /** + * A RESUME control was sent, but the file transfer is running normally. + */ + TOX_ERR_FILE_CONTROL_NOT_PAUSED, + /** + * A RESUME control was sent, but the file transfer was paused by the other + * party. Only the party that paused the transfer can resume it. + */ + TOX_ERR_FILE_CONTROL_DENIED, + /** + * A PAUSE control was sent, but the file transfer was already paused. + */ + TOX_ERR_FILE_CONTROL_ALREADY_PAUSED +} TOX_ERR_FILE_CONTROL; + +/** + * Sends a file control command to a friend for a given file transfer. + * + * @param friend_number The friend number of the friend the file is being + * transferred to. + * @param file_number The friend-specific identifier for the file transfer. + * @param control The control command to send. + * + * @return true on success. + */ +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, + TOX_ERR_FILE_CONTROL *error); + + +/** + * The function type for the `file_control` callback. + * + * When receiving TOX_FILE_CONTROL_CANCEL, the client should release the + * resources associated with the file number and consider the transfer failed. + * + * @param friend_number The friend number of the friend who is sending the file. + * @param file_number The friend-specific file number the data received is + * associated with. + * @param control The file control command received. + */ +typedef void tox_file_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, + void *user_data); + +/** + * Set the callback for the `file_control` event. Pass NULL to unset. + * + * This event is triggered when a file control command is received from a + * friend. + */ +void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *user_data); + + +/******************************************************************************* + * + * :: File transmission: sending + * + ******************************************************************************/ + + +typedef enum TOX_ERR_FILE_SEND { + TOX_ERR_FILE_SEND_OK, + TOX_ERR_FILE_SEND_NULL, + /** + * The friend_number passed did not designate a valid friend. + */ + TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED, + /** + * Filename length was 0. + */ + TOX_ERR_FILE_SEND_NAME_EMPTY, + /** + * Filename length exceeded 255 bytes. + */ + TOX_ERR_FILE_SEND_NAME_TOO_LONG, + /** + * Too many ongoing transfers. The maximum number of concurrent file transfers + * is 256 per friend per direction (sending and receiving). + */ + TOX_ERR_FILE_SEND_TOO_MANY +} TOX_ERR_FILE_SEND; + +/** + * Send a file transmission request. + * + * Maximum filename length is 255 bytes. The filename should generally just be + * a file name, not a path with directory names. + * + * If a non-zero file size is provided, this can be used by both sides to + * determine the sending progress. File size can be set to zero for streaming + * data of unknown size. + * + * File transmission occurs in chunks, which are requested through the + * `file_request_chunk` event. + * + * File numbers are stable across tox_save/tox_load cycles, so that file + * transfers can be resumed when a client restarts. The client needs to + * associate (friend Public Key, file number) with the local path of the file and + * persist this information to support resuming of transfers across restarts. + * + * If the file contents change during a transfer, the behaviour is unspecified + * in general. What will actually happen depends on the mode in which the file + * was modified and how the client determines the file size. + * + * - If the file size was increased + * - and sending mode was streaming (file_size = 0), the behaviour will be as + * expected. + * - and sending mode was file (file_size != 0), the file_request_chunk + * callback will receive length = 0 when Core thinks the file transfer has + * finished. If the client remembers the file size as it was when sending + * the request, it will terminate the transfer normally. If the client + * re-reads the size, it will think the friend cancelled the transfer. + * - If the file size was decreased + * - and sending mode was streaming, the behaviour is as expected. + * - and sending mode was file, the callback will return 0 at the new + * (earlier) end-of-file, signalling to the friend that the transfer was + * cancelled. + * - If the file contents were modified + * - at a position before the current read, the two files (local and remote) + * will differ after the transfer terminates. + * - at a position after the current read, the file transfer will succeed as + * expected. + * - In either case, both sides will regard the transfer as complete and + * successful. + * + * @param friend_number The friend number of the friend the file send request + * should be sent to. + * @param kind The meaning of the file to be sent. + * @param file_size Size in bytes of the file the client wants to send, 0 if + * unknown or streaming. + * @param filename Name of the file. Does not need to be the actual name. This + * name will be sent along with the file send request. + * @param filename_length Size in bytes of the filename. + * + * @return A file number used as an identifier in subsequent callbacks. This + * number is per friend. File numbers are reused after a transfer terminates. + */ +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, + uint8_t const *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); + + +typedef enum TOX_ERR_FILE_SEND_CHUNK { + TOX_ERR_FILE_SEND_CHUNK_OK, + /** + * The length parameter was non-zero, but data was NULL. + */ + TOX_ERR_FILE_SEND_CHUNK_NULL, + /** + * The friend_number passed did not designate a valid friend. + */ + TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED, + /** + * No file transfer with the given file number was found for the given friend. + */ + TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND, + /** + * Attempted to send more data than requested. The requested data size is + * adjusted according to maximum transmission unit and the expected end of + * the file. Trying to send more will result in no data being sent. + */ + TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE +} TOX_ERR_FILE_SEND_CHUNK; + +/** + * Send a chunk of file data to a friend. + * + * This function is called in response to the `file_request_chunk` callback. The + * length parameter should be equal to or less than the one received though the + * callback. If it is zero, the transfer is assumed complete. For files with + * known size, Core will know that the transfer is complete after the last byte + * has been received, so it is not necessary (though not harmful) to send a + * zero-length chunk to terminate. For streams, it is necessary for the last + * chunk sent to be zero-length. + * + * @return true on success. + */ +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t const *data, size_t length, + TOX_ERR_FILE_SEND_CHUNK *error); + + +/** + * The function type for the `file_request_chunk` callback. + * + * If the length parameter is 0, the file transfer is finished, and the client's + * resources associated with the file number should be released. After a call + * with zero length, the file number can be reused for future file transfers. + * + * If the requested position is not equal to the client's idea of the current + * file or stream position, it will need to seek. In case of read-once streams, + * the client should keep the last read chunk so that a seek back can be + * supported. A seek-back only ever needs to read from the last requested chunk. + * This happens when a chunk was requested, but the send failed. A seek-back + * request can occur an arbitrary number of times for any given chunk. + * + * In response to receiving this callback, the client should call the function + * `tox_file_send_chunk` with the requested chunk. If the number of bytes sent + * through that function is zero, the file transfer is assumed complete. A + * client may choose to send less than requested, if it is reading from a + * stream that doesn't have more data, yet, and it still wants to send some + * data to the other side. However, this will generally be less efficient than + * waiting for a full chunk size of data to be ready. + * + * @param friend_number The friend number of the receiving friend for this file. + * @param file_number The file transfer identifier returned by tox_file_send. + * @param position The file or stream position from which to continue reading. + * @param length The number of bytes requested for the current chunk. + */ +typedef void tox_file_request_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + size_t length, void *user_data); + +/** + * Set the callback for the `file_request_chunk` event. Pass NULL to unset. + */ +void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *function, void *user_data); + + +/******************************************************************************* + * + * :: File transmission: receiving + * + ******************************************************************************/ + + +/** + * The function type for the `file_receive` callback. + * + * The client should acquire resources to be associated with the file transfer. + * Incoming file transfers start in the PAUSED state. After this callback + * returns, a transfer can be rejected by sending a TOX_FILE_CONTROL_CANCEL + * control command before any other control commands. It can be accepted by + * sending TOX_FILE_CONTROL_RESUME. + * + * @param friend_number The friend number of the friend who is sending the file + * transfer request. + * @param file_number The friend-specific file number the data received is + * associated with. + */ +typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, + uint64_t file_size, uint8_t const *filename, size_t filename_length, void *user_data); + +/** + * Set the callback for the `file_receive` event. Pass NULL to unset. + * + * This event is triggered when a file transfer request is received. + */ +void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *user_data); + + +/** + * The function type for the `file_receive_chunk` callback. + * + * This function is first called when a file transfer request is received, and + * subsequently when a chunk of file data for an accepted request was received. + * + * When length is 0, the transfer is finished and the client should release the + * resources it acquired for the transfer. After a call with length = 0, the + * file number can be reused for new file transfers. + * + * If position is equal to file_size (received in the file_receive callback) + * when the transfer finishes, the file was received completely. Otherwise, if + * file_size was 0, streaming ended successfully when length is 0. + * + * @param friend_number The friend number of the friend who is sending the file. + * @param file_number The friend-specific file number the data received is + * associated with. + * @param position The file position of the first byte in data. + * @param data A byte array containing the received chunk. + * @param length The length of the received chunk. + */ +typedef void tox_file_receive_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + uint8_t const *data, size_t length, void *user_data); + +/** + * Set the callback for the `file_receive_chunk` event. Pass NULL to unset. + */ +void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *function, void *user_data); + + +/******************************************************************************* + * + * :: Group chat management + * + ******************************************************************************/ + + +/****************************************************************************** + * + * :: Group chat message sending and receiving + * + ******************************************************************************/ + + +/******************************************************************************* + * + * :: Low-level custom packet sending and receiving + * + ******************************************************************************/ + + +typedef enum TOX_ERR_SEND_CUSTOM_PACKET { + TOX_ERR_SEND_CUSTOM_PACKET_OK, + TOX_ERR_SEND_CUSTOM_PACKET_NULL, + /** + * The friend number did not designate a valid friend. + */ + TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED, + /** + * The first byte of data was not in the specified range for the packet type. + * This range is 200-254 for lossy, and 160-191 for lossless packets. + */ + TOX_ERR_SEND_CUSTOM_PACKET_INVALID, + /** + * Attempted to send an empty packet. + */ + TOX_ERR_SEND_CUSTOM_PACKET_EMPTY, + /** + * Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE. + */ + TOX_ERR_SEND_CUSTOM_PACKET_TOO_LONG, + /** + * Send queue size exceeded. + */ + TOX_ERR_SEND_CUSTOM_PACKET_SENDQ +} TOX_ERR_SEND_CUSTOM_PACKET; + + +/** + * Send a custom lossy packet to a friend. + * + * The first byte of data must be in the range 200-254. Maximum length of a + * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. + * + * Lossy packets behave like UDP packets, meaning they might never reach the + * other side or might arrive more than once (if someone is messing with the + * connection) or might arrive in the wrong order. + * + * Unless latency is an issue, it is recommended that you use lossless custom + * packets instead. + * + * @param friend_number The friend number of the friend this lossy packet + * should be sent to. + * @param data A byte array containing the packet data. + * @param length The length of the packet data byte array. + * + * @return true on success. + */ +bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, + TOX_ERR_SEND_CUSTOM_PACKET *error); + +/** + * The function type for the `friend_lossy_packet` callback. + * + * @param friend_number The friend number of the friend who sent a lossy packet. + * @param data A byte array containing the received packet data. + * @param length The length of the packet data byte array. + */ +typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, + void *user_data); + +/** + * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset. + */ +void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *function, void *user_data); + + +/** + * Send a custom lossless packet to a friend. + * + * The first byte of data must be in the range 160-191. Maximum length of a + * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. + * + * Lossless packet behaviour is comparable to TCP (reliability, arrive in order) + * but with packets instead of a stream. + * + * @param friend_number The friend number of the friend this lossless packet + * should be sent to. + * @param data A byte array containing the packet data. + * @param length The length of the packet data byte array. + * + * @return true on success. + */ +bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, + TOX_ERR_SEND_CUSTOM_PACKET *error); + +/** + * The function type for the `friend_lossless_packet` callback. + * + * @param friend_number The friend number of the friend who sent the packet. + * @param data A byte array containing the received packet data. + * @param length The length of the packet data byte array. + */ +typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, + void *user_data); + +/** + * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset. + */ +void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *function, void *user_data); + + + +/******************************************************************************* + * + * :: Low-level network information + * + ******************************************************************************/ + + +/** + * Writes the temporary DHT public key of this instance to a byte array. + * + * This can be used in combination with an externally accessible IP address and + * the bound port (from tox_get_udp_port) to run a temporary bootstrap node. + * + * Be aware that every time a new instance is created, the DHT public key + * changes, meaning this cannot be used to run a permanent bootstrap node. + * + * @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this + * parameter is NULL, this function has no effect. + */ +void tox_get_dht_id(Tox const *tox, uint8_t *dht_id); + + +typedef enum TOX_ERR_GET_PORT { + TOX_ERR_GET_PORT_OK, + /** + * The instance was not bound to any port. + */ + TOX_ERR_GET_PORT_NOT_BOUND +} TOX_ERR_GET_PORT; + +/** + * Return the UDP port this Tox instance is bound to. + */ +uint16_t tox_get_udp_port(Tox const *tox, TOX_ERR_GET_PORT *error); + +/** + * Return the TCP port this Tox instance is bound to. This is only relevant if + * the instance is acting as a TCP relay. + */ +uint16_t tox_get_tcp_port(Tox const *tox, TOX_ERR_GET_PORT *error); + #ifdef __cplusplus } From 3c7888d7523f876740084c7315e31f973920212b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Feb 2015 23:00:12 -0500 Subject: [PATCH 003/101] A bit of new api work done. --- toxcore/tox.c | 97 +++++++++++++++++++++++++++++++-- toxcore/tox.h | 8 ++- toxencryptsave/defines.h | 2 + toxencryptsave/toxencryptsave.c | 7 ++- toxencryptsave/toxencryptsave.h | 4 +- 5 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 toxencryptsave/defines.h diff --git a/toxcore/tox.c b/toxcore/tox.c index 124d7119..b509fc3b 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -20,7 +20,11 @@ * along with Tox. If not, see . * */ - +/* +TODO: +-replace bool with uint8_t +-remove enums (typedef enum in api to uint8_t) +*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -29,6 +33,8 @@ #include "group.h" #include "logger.h" +#include "../toxencryptsave/defines.h" + #define TOX_DEFINED typedef struct Messenger Tox; @@ -62,6 +68,9 @@ void tox_options_default(struct Tox_Options *options) { if (options) { memset(options, 0, sizeof(struct Tox_Options)); + options->ipv6_enabled = 1; + options->udp_enabled = 1; + options->proxy_type = TOX_PROXY_TYPE_NONE; } } @@ -85,22 +94,102 @@ void tox_options_free(struct Tox_Options *options) Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t length, TOX_ERR_NEW *error) { + if (!logger_get_global()) + logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); + if (data) { + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED); + return NULL; + } + } + + Messenger_Options m_options = {0}; + + if (options == NULL) { + m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + } else { + m_options.ipv6enabled = options->ipv6_enabled; + m_options.udp_disabled = !options->udp_enabled; + + switch (options->proxy_type) { + case TOX_PROXY_TYPE_HTTP: + m_options.proxy_info.proxy_type = TCP_PROXY_HTTP; + break; + + case TOX_PROXY_TYPE_SOCKS5: + m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5; + break; + + case TOX_PROXY_TYPE_NONE: + m_options.proxy_info.proxy_type = TCP_PROXY_NONE; + break; + + default: + SET_ERROR_PARAMETER(error, TOX_ERR_PROXY_TYPE); + return NULL; + } + + if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) { + if (options->proxy_port == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT); + return NULL; + } + + ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled); + + if (m_options.ipv6enabled) + m_options.proxy_info.ip_port.ip.family = AF_UNSPEC; + + if (!addr_resolve_or_parse_ip(options->proxy_address, &m_options.proxy_info.ip_port.ip, NULL)) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST); + //TODO: TOX_ERR_NEW_PROXY_NOT_FOUND if domain. + return NULL; + } + + m_options.proxy_info.ip_port.port = htons(options->proxy_port); + } + } + + Messenger *m = new_messenger(&m_options); + //TODO: TOX_ERR_NEW_MALLOC + //TODO: TOX_ERR_NEW_PORT_ALLOC + + if (!new_groupchats(m)) { + kill_messenger(m); + return NULL; + } + + if (messenger_load(m, data, length) == -1) { + /* TODO: uncomment this when tox is stable. + tox_kill(m); + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); + return NULL; + */ + } + + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); + return m; } void tox_kill(Tox *tox) { - + Messenger *m = tox; + kill_groupchats(m->group_chat_object); + kill_messenger(m); + logger_kill_global(); } size_t tox_save_size(Tox const *tox) { - + const Messenger *m = tox; + return messenger_size(m); } void tox_save(Tox const *tox, uint8_t *data) { - + const Messenger *m = tox; + messenger_save(m, data); } diff --git a/toxcore/tox.h b/toxcore/tox.h index 8dab7002..61f40539 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -418,12 +418,16 @@ typedef enum TOX_ERR_NEW { */ TOX_ERR_NEW_PORT_ALLOC, /** - * proxy_enabled was true, but the proxy_address passed had an invalid format + * proxy_type was invalid. + */ + TOX_ERR_PROXY_TYPE, + /** + * proxy_type was valid but the proxy_address passed had an invalid format * or was NULL. */ TOX_ERR_NEW_PROXY_BAD_HOST, /** - * proxy_enabled was true, but the proxy_port was invalid. + * proxy_type was valid, but the proxy_port was invalid. */ TOX_ERR_NEW_PROXY_BAD_PORT, /** diff --git a/toxencryptsave/defines.h b/toxencryptsave/defines.h new file mode 100644 index 00000000..e3fca073 --- /dev/null +++ b/toxencryptsave/defines.h @@ -0,0 +1,2 @@ +#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave" +#define TOX_ENC_SAVE_MAGIC_LENGTH 8 diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 9172f512..13a34dea 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -26,6 +26,7 @@ #endif #include "toxencryptsave.h" +#include "defines.h" #include "../toxcore/crypto_core.h" #include "../toxcore/tox.h" @@ -64,7 +65,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_save_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } /* This retrieves the salt used to encrypt the given data, which can then be passed to @@ -203,7 +204,7 @@ 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_save_size(tox); uint8_t temp_data[temp_size]; tox_save(tox, temp_data); @@ -220,7 +221,7 @@ 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_save_size(tox); uint8_t temp_data[temp_size]; tox_save(tox, temp_data); diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 169f736c..da13f312 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -30,8 +30,8 @@ extern "C" { #include -#ifndef __TOX_DEFINED__ -#define __TOX_DEFINED__ +#ifndef TOX_DEFINED +#define TOX_DEFINED typedef struct Tox Tox; #endif From fd56762a1bd3af1207ecb2e7ea1e895c46ae2cc8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Feb 2015 23:00:35 -0500 Subject: [PATCH 004/101] Code cleanups. --- toxcore/crypto_core.h | 2 +- toxcore/onion_client.c | 6 +++--- toxcore/onion_client.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index afd2f7b8..decc7fb9 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -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. diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 61034167..3643cb2f 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -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; @@ -1396,7 +1396,7 @@ Onion_Client *new_onion_client(Net_Crypto *c) 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); + 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; @@ -1412,7 +1412,7 @@ void kill_onion_client(Onion_Client *onion_c) 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); + 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); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index b4e7a1b7..6851d929 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -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]; From 7e2839e2d8f16f72143a9c405b5a410a11489eb3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 15 Feb 2015 20:20:06 -0500 Subject: [PATCH 005/101] New api progress. --- toxcore/Messenger.c | 2 +- toxcore/Messenger.h | 2 +- toxcore/tox.c | 115 +++++++++++++++++++++++++++++++++++++++++--- toxcore/tox.h | 6 +-- 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 4cf0edeb..194a633e 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2350,7 +2350,7 @@ static char *ID2String(const uint8_t *pk) * * 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) { uint32_t crypto_interval = crypto_run_interval(m->net_crypto); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index a9931d1f..367e65c7 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -891,7 +891,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: */ diff --git a/toxcore/tox.c b/toxcore/tox.c index b509fc3b..dbd8a96c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -20,11 +20,7 @@ * along with Tox. If not, see . * */ -/* -TODO: --replace bool with uint8_t --remove enums (typedef enum in api to uint8_t) -*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -157,6 +153,7 @@ Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t leng if (!new_groupchats(m)) { kill_messenger(m); + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); return NULL; } @@ -180,16 +177,120 @@ void tox_kill(Tox *tox) logger_kill_global(); } - size_t tox_save_size(Tox const *tox) { const Messenger *m = tox; return messenger_size(m); } - void tox_save(Tox const *tox, uint8_t *data) { const Messenger *m = tox; messenger_save(m, data); } + +static int address_to_ip(Messenger *m, char const *address, IP_Port *ip_port, IP_Port *ip_port_v4) +{ + if (!addr_parse_ip(address, &ip_port->ip)) { + if (m->options.udp_disabled) { /* Disable DNS when udp is disabled. */ + return -1; + } + + IP *ip_extra = NULL; + ip_init(&ip_port->ip, m->options.ipv6enabled); + + if (m->options.ipv6enabled && ip_port_v4) { + /* setup for getting BOTH: an IPv6 AND an IPv4 address */ + ip_port->ip.family = AF_UNSPEC; + ip_reset(&ip_port_v4->ip); + ip_extra = &ip_port_v4->ip; + } + + if (!addr_resolve(address, &ip_port->ip, ip_extra)) { + return -1; + } + } + + return 0; +} + +bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error) +{ + Messenger *m = tox; + bool ret = tox_add_tcp_relay(tox, address, port, public_key, error); + + if (!ret) { + return 0; + } + + if (m->options.udp_disabled) { + return ret; + } else { /* DHT only works on UDP. */ + if (DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key) == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_ADDRESS); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); + return 1; + } +} + +bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, + TOX_ERR_BOOTSTRAP *error) +{ + Messenger *m = tox; + IP_Port ip_port, ip_port_v4; + + if (port == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT); + return 0; + } + + if (address_to_ip(m, address, &ip_port, &ip_port_v4) == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_ADDRESS); + return 0; + } + + ip_port.port = htons(port); + add_tcp_relay(m->net_crypto, ip_port, public_key); + onion_add_bs_path_node(m->onion_c, ip_port, public_key); //TODO: move this + + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); + return 1; +} + +TOX_CONNECTION tox_get_connection_status(Tox const *tox) +{ + const Messenger *m = tox; + + if (onion_isconnected(m->onion_c)) { + if (DHT_non_lan_connected(m->dht)) { + return TOX_CONNECTION_UDP; + } + + return TOX_CONNECTION_TCP; + } + + return TOX_CONNECTION_NONE; +} + + +void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function, void *user_data) +{ + //TODO +} + +uint32_t tox_iteration_interval(Tox const *tox) +{ + const Messenger *m = tox; + return messenger_run_interval(m); +} + +void tox_iteration(Tox *tox) +{ + Messenger *m = tox; + do_messenger(m); + do_groupchats(m->group_chat_object); +} + diff --git a/toxcore/tox.h b/toxcore/tox.h index 61f40539..056dcd31 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -571,16 +571,14 @@ typedef enum TOX_CONNECTION { * is connected through a TCP relay, only. For a friend, this means that the * connection to that particular friend goes through a TCP relay. */ - TOX_CONNECTION_TCP4, - TOX_CONNECTION_TCP6, + TOX_CONNECTION_TCP, /** * A UDP connection has been established. For the own instance, this means it * is able to send UDP packets to DHT nodes, but may still be connected to * a TCP relay. For a friend, this means that the connection to that * particular friend was built using direct UDP packets. */ - TOX_CONNECTION_UDP4, - TOX_CONNECTION_UDP6 + TOX_CONNECTION_UDP } TOX_CONNECTION; From 8532dc8ae71396a3b7f0731d585c086d180e7e5f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 16 Feb 2015 20:25:44 -0500 Subject: [PATCH 006/101] Allow empty names and status messages. --- toxcore/Messenger.c | 35 +++++++++++++++++++---------------- toxcore/Messenger.h | 2 +- toxcore/group.c | 8 +++++--- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 194a633e..1bcc1f51 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -204,8 +204,7 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta m->friendlist[i].friendcon_id = friendcon_id; m->friendlist[i].friendrequest_lastsent = 0; id_copy(m->friendlist[i].real_pk, real_pk); - m->friendlist[i].statusmessage = calloc(1, 1); - m->friendlist[i].statusmessage_length = 1; + m->friendlist[i].statusmessage_length = 0; m->friendlist[i].userstatus = USERSTATUS_NONE; m->friendlist[i].avatar_info_sent = 0; m->friendlist[i].avatar_recv_data = NULL; @@ -334,7 +333,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber) if (m->friendlist[friendnumber].status == FRIEND_ONLINE) remove_online_friend(m, friendnumber); - free(m->friendlist[friendnumber].statusmessage); free(m->friendlist[friendnumber].avatar_recv_data); remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); @@ -451,7 +449,7 @@ uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t */ static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) { - if (length > MAX_NAME_LENGTH || length == 0) + if (length > MAX_NAME_LENGTH) return 0; return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0); @@ -485,13 +483,15 @@ int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint1 */ int setname(Messenger *m, const uint8_t *name, uint16_t length) { - if (length > MAX_NAME_LENGTH || length == 0) + if (length > MAX_NAME_LENGTH) return -1; - if (m->name_length == length && memcmp(name, m->name, length) == 0) + if (m->name_length == length && (length == 0 || memcmp(name, m->name, length) == 0)) return 0; - memcpy(m->name, name, length); + if (length) + memcpy(m->name, name, length); + m->name_length = length; uint32_t i; @@ -550,10 +550,12 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length) if (length > MAX_STATUSMESSAGE_LENGTH) return -1; - if (m->statusmessage_length == length && memcmp(m->statusmessage, status, length) == 0) + if (m->statusmessage_length == length && (length == 0 || memcmp(m->statusmessage, status, length) == 0)) return 0; - memcpy(m->statusmessage, status, length); + if (length) + memcpy(m->statusmessage, status, length); + m->statusmessage_length = length; uint32_t i; @@ -859,10 +861,12 @@ static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, co if (friend_not_valid(m, friendnumber)) return -1; - uint8_t *newstatus = calloc(length + 1, 1); - memcpy(newstatus, status, length); - free(m->friendlist[friendnumber].statusmessage); - m->friendlist[friendnumber].statusmessage = newstatus; + if (length > MAX_STATUSMESSAGE_LENGTH) + return -1; + + if (length) + memcpy(m->friendlist[friendnumber].statusmessage, status, length); + m->friendlist[friendnumber].statusmessage_length = length; return 0; } @@ -1632,7 +1636,6 @@ void kill_messenger(Messenger *m) kill_networking(m->net); for (i = 0; i < m->numfriends; ++i) { - free(m->friendlist[i].statusmessage); free(m->friendlist[i].avatar_recv_data); } @@ -1990,7 +1993,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_NICKNAME: { - if (data_length > MAX_NAME_LENGTH || data_length == 0) + if (data_length > MAX_NAME_LENGTH) break; /* Make sure the NULL terminator is present. */ @@ -2009,7 +2012,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_STATUSMESSAGE: { - if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) + if (data_length > MAX_STATUSMESSAGE_LENGTH) break; /* Make sure the NULL terminator is present. */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 367e65c7..91faff66 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -201,7 +201,7 @@ 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; diff --git a/toxcore/group.c b/toxcore/group.c index c1a60851..786a9cdd 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -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; - memcpy(g->group[peer_index].nick, nick, nick_len); + 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) From 3f11d106daeeeacf13e6207a7042a90ece7c9325 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 16 Feb 2015 20:57:44 -0500 Subject: [PATCH 007/101] More new api work done. m_copy_self_statusmessage no longer takes a buffer length argument. --- toxcore/Messenger.c | 8 ++- toxcore/Messenger.h | 2 +- toxcore/tox.c | 117 +++++++++++++++++++++++++++++++++++++++++++- toxcore/tox.h | 3 +- 4 files changed, 120 insertions(+), 10 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 1bcc1f51..55464cb5 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -760,12 +760,10 @@ int m_get_self_statusmessage_size(const Messenger *m) return m->statusmessage_length; } -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) { - int msglen = MIN(maxlen, m->statusmessage_length); - memcpy(buf, m->statusmessage, msglen); - memset(buf + msglen, 0, maxlen - msglen); - return msglen; + memcpy(buf, m->statusmessage, m->statusmessage_length); + return m->statusmessage_length; } uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber) diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 91faff66..1139fb74 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -479,7 +479,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. diff --git a/toxcore/tox.c b/toxcore/tox.c index dbd8a96c..71397b9e 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -185,8 +185,10 @@ size_t tox_save_size(Tox const *tox) void tox_save(Tox const *tox, uint8_t *data) { - const Messenger *m = tox; - messenger_save(m, data); + if (data) { + const Messenger *m = tox; + messenger_save(m, data); + } } static int address_to_ip(Messenger *m, char const *address, IP_Port *ip_port, IP_Port *ip_port_v4) @@ -216,6 +218,11 @@ static int address_to_ip(Messenger *m, char const *address, IP_Port *ip_port, IP bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error) { + if (!address || !public_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL); + return 0; + } + Messenger *m = tox; bool ret = tox_add_tcp_relay(tox, address, port, public_key, error); @@ -239,6 +246,11 @@ bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const * bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error) { + if (!address || !public_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL); + return 0; + } + Messenger *m = tox; IP_Port ip_port, ip_port_v4; @@ -294,3 +306,104 @@ void tox_iteration(Tox *tox) do_groupchats(m->group_chat_object); } +void tox_self_get_address(Tox const *tox, uint8_t *address) +{ + if (address) { + const Messenger *m = tox; + getaddress(m, address); + } +} + +void tox_self_set_nospam(Tox *tox, uint32_t nospam) +{ + Messenger *m = tox; + set_nospam(&(m->fr), nospam); +} + +uint32_t tox_self_get_nospam(Tox const *tox) +{ + const Messenger *m = tox; + return get_nospam(&(m->fr)); +} + +void tox_self_get_public_key(Tox const *tox, uint8_t *public_key) +{ + const Messenger *m = tox; + + if (public_key) + memcpy(public_key, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); +} + +void tox_self_get_private_key(Tox const *tox, uint8_t *private_key) +{ + const Messenger *m = tox; + + if (private_key) + memcpy(private_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); +} + +bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET_INFO *error) +{ + if (!name && length != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL); + return 0; + } + + Messenger *m = tox; + + if (setname(m, name, length) == 0) { + //TODO: function to set different per group names? + send_name_all_groups(m->group_chat_object); + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); + return 1; + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG); + return 0; + } +} + +size_t tox_self_get_name_size(Tox const *tox) +{ + const Messenger *m = tox; + return m_get_self_name_size(m); +} + +void tox_self_get_name(Tox const *tox, uint8_t *name) +{ + if (name) { + const Messenger *m = tox; + getself_name(m, name); + } +} + +bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, TOX_ERR_SET_INFO *error) +{ + if (!status && length != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL); + return 0; + } + + Messenger *m = tox; + + if (m_set_statusmessage(m, status, length) == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); + return 1; + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG); + return 0; + } +} + +size_t tox_self_get_status_message_size(Tox const *tox) +{ + const Messenger *m = tox; + return m_get_self_statusmessage_size(m); +} + +void tox_self_get_status_message(Tox const *tox, uint8_t *status) +{ + if (status) { + const Messenger *m = tox; + m_copy_self_statusmessage(m, status); + } +} diff --git a/toxcore/tox.h b/toxcore/tox.h index 056dcd31..2dc1594c 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -730,7 +730,6 @@ size_t tox_self_get_name_size(Tox const *tox); */ void tox_self_get_name(Tox const *tox, uint8_t *name); - /** * Set the client's status message. * @@ -760,7 +759,7 @@ size_t tox_self_get_status_message_size(Tox const *tox); * Call tox_self_status_message_size to find out how much memory to allocate for * the result. * - * @param name A valid memory location large enough to hold the status message. + * @param status A valid memory location large enough to hold the status message. * If this parameter is NULL, the function has no effect. */ void tox_self_get_status_message(Tox const *tox, uint8_t *status); From 99ee86b865950f9044f03b189b5dd946b617735c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Feb 2015 10:29:18 -0500 Subject: [PATCH 008/101] Messenger add friends functions error code fixes. Removed unknown error. norequest function now returns proper error codes. --- toxcore/Messenger.c | 19 ++++++------------- toxcore/Messenger.h | 7 ++++--- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 55464cb5..1809fc4c 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -194,7 +194,7 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta int friendcon_id = new_friend_connection(m->fr_c, real_pk); if (friendcon_id == -1) - return FAERR_UNKNOWN; + return FAERR_NOMEM; uint32_t i; @@ -227,7 +227,7 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta } } - return FAERR_UNKNOWN; + return FAERR_NOMEM; } /* @@ -241,7 +241,6 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte). * return FAERR_OWNKEY if user's own key. * return FAERR_ALREADYSENT if friend request already sent or already a friend. - * return FAERR_UNKNOWN for unknown error. * return FAERR_BADCHECKSUM if bad checksum in address. * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different. * (the nospam for that friend was set to the new one). @@ -303,21 +302,15 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk) { if (getfriend_id(m, real_pk) != -1) - return -1; + return FAERR_ALREADYSENT; if (!public_key_valid(real_pk)) - return -1; + return FAERR_BADCHECKSUM; if (id_equal(real_pk, m->net_crypto->self_public_key)) - return -1; + return FAERR_OWNKEY; - int32_t ret = init_new_friend(m, real_pk, FRIEND_CONFIRMED); - - if (ret < 0) { - return -1; - } else { - return ret; - } + return init_new_friend(m, real_pk, FRIEND_CONFIRMED); } /* Remove a friend. diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 1139fb74..b1f1c152 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -95,7 +95,6 @@ enum { FAERR_NOMESSAGE = -2, FAERR_OWNKEY = -3, FAERR_ALREADYSENT = -4, - FAERR_UNKNOWN = -5, FAERR_BADCHECKSUM = -6, FAERR_SETNEWNOSPAM = -7, FAERR_NOMEM = -8 @@ -329,7 +328,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 +338,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); From 7cefc9c4582c367092cd6187ea924da9a1fcf2f0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Feb 2015 15:46:14 -0500 Subject: [PATCH 009/101] Fixed friend_not_valid function. It now returns if friend is valid or not not only if memory location is valid. --- toxcore/Messenger.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 1809fc4c..f566a344 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -44,7 +44,13 @@ static int send_avatar_data_control(const Messenger *m, const uint32_t friendnum // friend_not_valid determines if the friendnumber passed is valid in the Messenger object static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) { - return (unsigned int)friendnumber >= m->numfriends; + if ((unsigned int)friendnumber < m->numfriends) { + if (m->friendlist[friendnumber].status != 0) { + return 0; + } + } + + return 1; } static int add_online_friend(Messenger *m, int32_t friendnumber) @@ -113,12 +119,8 @@ int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk) if (friend_not_valid(m, friendnumber)) return -1; - if (m->friendlist[friendnumber].status > 0) { - memcpy(real_pk, m->friendlist[friendnumber].real_pk, crypto_box_PUBLICKEYBYTES); - return 0; - } - - return -1; + memcpy(real_pk, m->friendlist[friendnumber].real_pk, crypto_box_PUBLICKEYBYTES); + return 0; } /* return friend connection id on success. @@ -364,7 +366,7 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) if (friend_not_valid(m, friendnumber)) return 0; - return m->friendlist[friendnumber].status > NOFRIEND; + return 1; } /* Send a text chat message to an online friend. From c6a59e64b7a7fb86ed8a99c21a0b7b023559b0ea Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Feb 2015 15:49:22 -0500 Subject: [PATCH 010/101] Updated types in Messenger callbacks to fit with the ones in the new api. Friend number changed from int32_t to uint32_t. Some lengths changed to size_t. --- toxav/msi.c | 5 +- toxav/rtp.c | 2 +- toxcore/Messenger.c | 54 +++++++++--------- toxcore/Messenger.h | 114 +++++++++++++++++++------------------- toxcore/friend_requests.c | 2 +- toxcore/friend_requests.h | 6 +- toxcore/group.c | 2 +- 7 files changed, 95 insertions(+), 90 deletions(-) diff --git a/toxav/msi.c b/toxav/msi.c index fda41d0c..dcb7b62a 100644 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -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 */ diff --git a/toxav/rtp.c b/toxav/rtp.c index 2af89ebf..63c2cdcb 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -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, uint32_t length, void *object ) { RTPSession *session = object; RTPMessage *msg; diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f566a344..4a173de7 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -886,83 +886,83 @@ void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno) m->friendlist[friendnumber].receives_read_receipts = yesno; } -/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */ /* Set the function that will be executed when a friend request is received. */ -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) { - void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, uint16_t, void *) = (void *)function; + void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *) = (void *)function; callback_friendrequest(&(m->fr), handle_friendrequest, m, userdata); } /* Set the function that will be executed when a message from a friend is received. */ -void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *), +void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), void *userdata) { m->friend_message = function; m->friend_message_userdata = userdata; } -void m_callback_action(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *), +void m_callback_action(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), void *userdata) { m->friend_action = function; m->friend_action_userdata = userdata; } -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) { m->friend_namechange = function; m->friend_namechange_userdata = userdata; } -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) { m->friend_statusmessagechange = function; m->friend_statuschange_userdata = userdata; } -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, uint8_t, void *), void *userdata) { m->friend_userstatuschange = function; m->friend_userstatuschange_userdata = userdata; } -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, uint8_t, void *), void *userdata) { m->friend_typingchange = function; m->friend_typingchange_userdata = userdata; } -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) { m->read_receipt = function; m->read_receipt_userdata = userdata; } -void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *), void *userdata) +void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), + void *userdata) { m->friend_connectionstatuschange = function; m->friend_connectionstatuschange_userdata = userdata; } -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) { m->friend_connectionstatuschange_internal = function; m->friend_connectionstatuschange_internal_userdata = userdata; } -void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, void *), +void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, void *), void *userdata) { m->avatar_info_recv = function; m->avatar_info_recv_userdata = userdata; } -void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, +void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *), void *userdata) { m->avatar_data_recv = function; @@ -1027,9 +1027,9 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_ /* 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)) { m->group_invite = function; } @@ -1050,9 +1050,10 @@ 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, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata) */ -void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, +void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint64_t, + const uint8_t *, uint16_t, void *), void *userdata) { m->file_sendrequest = function; @@ -1061,10 +1062,10 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int3 /* 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, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata) * */ -void callback_file_control(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t, uint8_t, +void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, void *), void *userdata) { m->file_filecontrol = function; @@ -1073,10 +1074,11 @@ void callback_file_control(Messenger *m, void (*function)(Messenger *m, int32_t, /* 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, uint8_t filenumber, uint8_t *data, uint16_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 callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, const uint8_t *, + uint16_t length, void *), void *userdata) { m->file_filedata = function; @@ -1397,7 +1399,7 @@ static int handle_filecontrol(const Messenger *m, int32_t friendnumber, uint8_t * * Function(Messenger *m, int 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) { m->msi_packet = function; @@ -1430,7 +1432,7 @@ static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_ } 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), + int (*packet_handler_callback)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object) { if (friend_not_valid(m, friendnumber)) @@ -1481,7 +1483,7 @@ static int handle_custom_lossless_packet(void *object, int friend_num, const uin } 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), + int (*packet_handler_callback)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object) { if (friend_not_valid(m, friendnumber)) @@ -2839,7 +2841,7 @@ 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(Messenger const *m, int32_t *out_list, uint32_t list_size) +uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size) { if (!out_list) return 0; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index b1f1c152..db0777cb 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -222,12 +222,12 @@ typedef struct { 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, uint32_t len, void *object); void *object; } lossy_packethandlers[PACKET_ID_LOSSY_RANGE_SIZE]; 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, uint32_t len, void *object); void *object; } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; } Friend; @@ -270,43 +270,43 @@ 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, 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)(struct Messenger *m, uint32_t, const uint8_t *, size_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, uint8_t, void *); void *friend_userstatuschange_userdata; - void (*friend_typingchange)(struct Messenger *m, int32_t, uint8_t, void *); + void (*friend_typingchange)(struct Messenger *m, uint32_t, uint8_t, 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)(struct Messenger *m, uint32_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, uint8_t, 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_info_recv)(struct Messenger *m, uint32_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 (*avatar_data_recv)(struct Messenger *m, uint32_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, uint8_t, uint64_t, const uint8_t *, uint16_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, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, 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, uint8_t, const uint8_t *, uint16_t length, void *); void *file_filedata_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; Messenger_Options options; @@ -624,50 +624,50 @@ uint8_t m_get_istyping(const Messenger *m, int32_t friendnumber); void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno); /* 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, 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 m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_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) + * Function format is: function(uint32_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 m_callback_action(Messenger *m, void (*function)(Messenger *m, uint32_t, 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, uint8_t, 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, uint8_t, 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 @@ -675,10 +675,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. @@ -688,10 +688,10 @@ 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, uint8_t, 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); @@ -701,14 +701,14 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess * information requests. * * Function format is: - * function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata) + * function(Tox *tox, uint32_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. * */ -void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, void *), +void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, void *), void *userdata); @@ -717,7 +717,7 @@ void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t * 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) + * function(Tox *tox, uint32_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 @@ -732,7 +732,7 @@ void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t * 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 *, +void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *), void *userdata); @@ -741,9 +741,9 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t /* 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. * @@ -757,25 +757,27 @@ 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, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata) */ -void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, +void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint64_t, + const uint8_t *, uint16_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, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata) * */ -void callback_file_control(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t, uint8_t, +void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, 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, uint8_t filenumber, uint8_t *data, uint16_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 callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, const uint8_t *, + uint16_t length, void *), void *userdata); /* Send a file send request. @@ -823,9 +825,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. @@ -843,7 +845,7 @@ int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, * 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), + int (*packet_handler_callback)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object); /* High level function to send custom lossy packets. @@ -862,7 +864,7 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin * 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), + int (*packet_handler_callback)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object); /* High level function to send custom lossless packets. @@ -918,6 +920,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 diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index e4a10008..dae1694a 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -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; diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index 86069f3b..ae21f7dc 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -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. diff --git a/toxcore/group.c b/toxcore/group.c index 786a9cdd..c688ccff 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -1236,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; From 61ca9529a1314aadd9085ce1b7ffdf8b6bce7c81 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Feb 2015 16:21:47 -0500 Subject: [PATCH 011/101] More new api functions implemented. Some small self explainatory changes to the api. --- toxcore/tox.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++ toxcore/tox.h | 18 ++-- 2 files changed, 251 insertions(+), 6 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 71397b9e..a9c7d4dd 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -407,3 +407,242 @@ void tox_self_get_status_message(Tox const *tox, uint8_t *status) m_copy_self_statusmessage(m, status); } } + +void tox_self_set_status(Tox *tox, TOX_STATUS user_status) +{ + Messenger *m = tox; + m_set_userstatus(m, user_status); +} + +TOX_STATUS tox_self_get_status(Tox const *tox) +{ + const Messenger *m = tox; + return m_get_self_userstatus(m); +} + +static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error) +{ + switch (ret) { + case FAERR_TOOLONG: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_TOO_LONG); + break; + + case FAERR_NOMESSAGE: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE); + break; + + case FAERR_OWNKEY: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OWN_KEY); + break; + + case FAERR_ALREADYSENT: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT); + break; + + case FAERR_BADCHECKSUM: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM); + break; + + case FAERR_SETNEWNOSPAM: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM); + break; + + case FAERR_NOMEM: + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC); + break; + + } +} + +uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message, size_t length, + TOX_ERR_FRIEND_ADD *error) +{ + if (!address || !message) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL); + return UINT32_MAX; + } + + Messenger *m = tox; + int32_t ret = m_addfriend(m, address, message, length); + + if (ret >= 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); + return ret; + } + + set_friend_error(ret, error); + return UINT32_MAX; +} + +uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error) +{ + if (!public_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL); + return UINT32_MAX; + } + + Messenger *m = tox; + int32_t ret = m_addfriend_norequest(m, public_key); + + if (ret >= 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); + return ret; + } + + set_friend_error(ret, error); + return UINT32_MAX; +} + +bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error) +{ + Messenger *m = tox; + int ret = m_delfriend(m, friend_number); + + //TODO handle if realloc fails? + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_OK); + return 1; +} + +uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error) +{ + if (!public_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL); + return UINT32_MAX; + } + + const Messenger *m = tox; + int32_t ret = getfriend_id(m, public_key); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND); + return UINT32_MAX; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK); + return ret; +} + +bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t *public_key, + TOX_ERR_FRIEND_GET_PUBLIC_KEY *error) +{ + if (!public_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL); + return 0; + } + + const Messenger *m = tox; + + if (get_real_pk(m, friend_number, public_key) == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK); + return 1; +} + +bool tox_friend_exists(Tox const *tox, uint32_t friend_number) +{ + const Messenger *m = tox; + return m_friend_exists(m, friend_number); +} + +size_t tox_friend_list_size(Tox const *tox) +{ + const Messenger *m = tox; + return count_friendlist(m); +} + +void tox_friend_list(Tox const *tox, uint32_t *list) +{ + if (list) { + const Messenger *m = tox; + //TODO: size parameter? + copy_friendlist(m, list, tox_friend_list_size(tox)); + } +} + +size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +{ + const Messenger *m = tox; + int ret = m_get_name_size(m, friend_number); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return SIZE_MAX; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return ret; +} + +bool tox_friend_get_name(Tox const *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error) +{ + if (!name) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL); + return 0; + } + + const Messenger *m = tox; + int ret = getname(m, friend_number, name); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return 1; +} + +void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_friendmessage(m, function, user_data); +} + +size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +{ + const Messenger *m = tox; + int ret = m_get_statusmessage_size(m, friend_number); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return SIZE_MAX; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return ret; +} + +bool tox_friend_get_status_message(Tox const *tox, uint32_t friend_number, uint8_t *message, + TOX_ERR_FRIEND_QUERY *error) +{ + if (!message) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL); + return 0; + } + + const Messenger *m = tox; + //TODO: size parameter? + int ret = m_copy_statusmessage(m, friend_number, message, m_get_statusmessage_size(m, friend_number)); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return 1; +} + +void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_statusmessage(m, function, user_data); +} diff --git a/toxcore/tox.h b/toxcore/tox.h index 2dc1594c..1a189ae3 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -274,7 +274,11 @@ typedef enum TOX_STATUS { * User is busy. Signals to other clients that this client does not * currently wish to communicate. */ - TOX_STATUS_BUSY + TOX_STATUS_BUSY, + /** + * Invalid status used when function returns an error. + */ + TOX_STATUS_INVALID } TOX_STATUS; @@ -833,7 +837,7 @@ typedef enum TOX_ERR_FRIEND_ADD { * be the same as before. Deleting a friend creates a gap in the friend number * set, which is filled by the next adding of a friend. * - * If more than UINT32_MAX friends are added, this function causes undefined + * If more than INT32_MAX friends are added, this function causes undefined * behaviour. * * @param address The address of the friend (returned by tox_self_get_address of @@ -841,7 +845,7 @@ typedef enum TOX_ERR_FRIEND_ADD { * @param message The message that will be sent along with the friend request. * @param length The length of the data byte array. * - * @return the friend number. + * @return the friend number on success, UINT32_MAX on failure. */ uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message, size_t length, TOX_ERR_FRIEND_ADD *error); @@ -862,7 +866,7 @@ uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message * @param public_key A byte array of length TOX_PUBLIC_KEY_SIZE containing the * Public Key (not the Address) of the friend to add. * - * @return the friend number. + * @return the friend number on success, UINT32_MAX on failure. * @see tox_friend_add for a more detailed description of friend numbers. */ uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error); @@ -909,6 +913,7 @@ typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { /** * Return the friend number associated with that Public Key. * + * @return the friend number on success, UINT32_MAX on failure. * @param public_key A byte array containing the Public Key. */ uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); @@ -916,6 +921,7 @@ uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, + TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL, /** * No friend with the given number exists on the friend list. */ @@ -990,7 +996,7 @@ typedef enum TOX_ERR_FRIEND_QUERY { /** * Return the length of the friend's name. If the friend number is invalid, the - * return value is unspecified. + * return value is SIZE_MAX. * * The return value is equal to the `length` argument received by the last * `friend_name` callback. @@ -1034,7 +1040,7 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user /** * Return the length of the friend's status message. If the friend number is - * invalid, the return value is unspecified. + * invalid, the return value is SIZE_MAX. */ size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); From 52a0753e52cb9095075c6fcc3538de965132e5b8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Feb 2015 18:22:04 -0500 Subject: [PATCH 012/101] Apparently enums are bad for wrappers and doing this makes wrapping toxcore easier. --- toxcore/tox.h | 116 ++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index 1a189ae3..a3973ae9 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -83,7 +83,7 @@ extern "C" { * It is possible to run multiple concurrent threads with a Tox instance for * each thread. It is also possible to run all Tox instances in the same thread. * A common way to run Tox (multiple or single instance) is to have one thread - * running a simple tox_iteration loop, sleeping for tox_iteration_time + * running a simple tox_iteration loop, sleeping for tox_iteration_interval * milliseconds on each iteration. * * If you want to access a single Tox instance from multiple threads, access @@ -260,7 +260,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); /** * Represents the possible statuses a client can have. */ -typedef enum TOX_STATUS { +enum TOX_STATUS { /** * User is online and available. */ @@ -279,8 +279,8 @@ typedef enum TOX_STATUS { * Invalid status used when function returns an error. */ TOX_STATUS_INVALID -} TOX_STATUS; - +}; +typedef uint8_t TOX_STATUS; /******************************************************************************* * @@ -289,7 +289,7 @@ typedef enum TOX_STATUS { ******************************************************************************/ -typedef enum TOX_PROXY_TYPE { +enum TOX_PROXY_TYPE { /** * Don't use a proxy. */ @@ -302,8 +302,8 @@ typedef enum TOX_PROXY_TYPE { * SOCKS proxy for simple socket pipes. */ TOX_PROXY_TYPE_SOCKS5 -} TOX_PROXY_TYPE; - +}; +typedef uint8_t TOX_PROXY_TYPE; /** * This struct contains all the startup options for Tox. You can either allocate @@ -370,13 +370,14 @@ struct Tox_Options { void tox_options_default(struct Tox_Options *options); -typedef enum TOX_ERR_OPTIONS_NEW { +enum TOX_ERR_OPTIONS_NEW { TOX_ERR_OPTIONS_NEW_OK, /** * The function failed to allocate enough memory for the options struct. */ TOX_ERR_OPTIONS_NEW_MALLOC -} TOX_ERR_OPTIONS_NEW; +}; +typedef uint8_t TOX_ERR_OPTIONS_NEW; /** * Allocates a new Tox_Options object and initialises it with the default @@ -407,7 +408,7 @@ void tox_options_free(struct Tox_Options *options); ******************************************************************************/ -typedef enum TOX_ERR_NEW { +enum TOX_ERR_NEW { TOX_ERR_NEW_OK, TOX_ERR_NEW_NULL, /** @@ -450,8 +451,8 @@ typedef enum TOX_ERR_NEW { * causes this error. */ TOX_ERR_NEW_LOAD_BAD_FORMAT -} TOX_ERR_NEW; - +}; +typedef uint8_t TOX_ERR_NEW; /** * @brief Creates and initialises a new Tox instance with the options passed. @@ -511,7 +512,7 @@ void tox_save(Tox const *tox, uint8_t *data); ******************************************************************************/ -typedef enum TOX_ERR_BOOTSTRAP { +enum TOX_ERR_BOOTSTRAP { TOX_ERR_BOOTSTRAP_OK, TOX_ERR_BOOTSTRAP_NULL, /** @@ -523,7 +524,8 @@ typedef enum TOX_ERR_BOOTSTRAP { * The port passed was invalid. The valid port range is (1, 65535). */ TOX_ERR_BOOTSTRAP_BAD_PORT -} TOX_ERR_BOOTSTRAP; +}; +typedef uint8_t TOX_ERR_BOOTSTRAP; /** * Sends a "get nodes" request to the given bootstrap node with IP, port, and @@ -564,7 +566,7 @@ bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t con TOX_ERR_BOOTSTRAP *error); -typedef enum TOX_CONNECTION { +enum TOX_CONNECTION { /** * There is no connection. This instance, or the friend the state change is * about, is now offline. @@ -583,8 +585,8 @@ typedef enum TOX_CONNECTION { * particular friend was built using direct UDP packets. */ TOX_CONNECTION_UDP -} TOX_CONNECTION; - +}; +typedef uint8_t TOX_CONNECTION; /** * Return whether we are connected to the DHT. The return value is equal to the @@ -687,15 +689,15 @@ void tox_self_get_private_key(Tox const *tox, uint8_t *private_key); * Common error codes for all functions that set a piece of user-visible * client information. */ -typedef enum TOX_ERR_SET_INFO { +enum TOX_ERR_SET_INFO { TOX_ERR_SET_INFO_OK, TOX_ERR_SET_INFO_NULL, /** * Information length exceeded maximum permissible size. */ TOX_ERR_SET_INFO_TOO_LONG -} TOX_ERR_SET_INFO; - +}; +typedef uint8_t TOX_ERR_SET_INFO; /** * Set the nickname for the Tox client. @@ -789,7 +791,7 @@ TOX_STATUS tox_self_get_status(Tox const *tox); ******************************************************************************/ -typedef enum TOX_ERR_FRIEND_ADD { +enum TOX_ERR_FRIEND_ADD { TOX_ERR_FRIEND_ADD_OK, TOX_ERR_FRIEND_ADD_NULL, /** @@ -823,7 +825,8 @@ typedef enum TOX_ERR_FRIEND_ADD { * A memory allocation failed when trying to increase the friend list size. */ TOX_ERR_FRIEND_ADD_MALLOC -} TOX_ERR_FRIEND_ADD; +}; +typedef uint8_t TOX_ERR_FRIEND_ADD; /** * Add a friend to the friend list and send a friend request. @@ -872,13 +875,14 @@ uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error); -typedef enum TOX_ERR_FRIEND_DELETE { +enum TOX_ERR_FRIEND_DELETE { TOX_ERR_FRIEND_DELETE_OK, /** * There was no friend with the given friend number. No friends were deleted. */ TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND -} TOX_ERR_FRIEND_DELETE; +}; +typedef uint8_t TOX_ERR_FRIEND_DELETE; /** * Remove a friend from the friend list. @@ -901,14 +905,15 @@ bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE * ******************************************************************************/ -typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { +enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL, /** * No friend with the given Public Key exists on the friend list. */ TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND -} TOX_ERR_FRIEND_BY_PUBLIC_KEY; +}; +typedef uint8_t TOX_ERR_FRIEND_BY_PUBLIC_KEY; /** * Return the friend number associated with that Public Key. @@ -919,14 +924,15 @@ typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); -typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { +enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL, /** * No friend with the given number exists on the friend list. */ TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND -} TOX_ERR_FRIEND_GET_PUBLIC_KEY; +}; +typedef uint8_t TOX_ERR_FRIEND_GET_PUBLIC_KEY; /** * Copies the Public Key associated with a given friend number to a byte array. @@ -979,7 +985,7 @@ void tox_friend_list(Tox const *tox, uint32_t *list); /** * Common error codes for friend state query functions. */ -typedef enum TOX_ERR_FRIEND_QUERY { +enum TOX_ERR_FRIEND_QUERY { TOX_ERR_FRIEND_QUERY_OK, /** * The pointer parameter for storing the query result (name, message) was @@ -991,8 +997,8 @@ typedef enum TOX_ERR_FRIEND_QUERY { * The friend_number did not designate a valid friend. */ TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND -} TOX_ERR_FRIEND_QUERY; - +}; +typedef uint8_t TOX_ERR_FRIEND_QUERY; /** * Return the length of the friend's name. If the friend number is invalid, the @@ -1180,13 +1186,14 @@ void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void * ******************************************************************************/ -typedef enum TOX_ERR_SET_TYPING { +enum TOX_ERR_SET_TYPING { TOX_ERR_SET_TYPING_OK, /** * The friend number did not designate a valid friend. */ TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND -} TOX_ERR_SET_TYPING; +}; +typedef uint8_t TOX_ERR_SET_TYPING; /** * Set the client's typing status for a friend. @@ -1201,7 +1208,7 @@ typedef enum TOX_ERR_SET_TYPING { bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error); -typedef enum TOX_ERR_SEND_MESSAGE { +enum TOX_ERR_SEND_MESSAGE { TOX_ERR_SEND_MESSAGE_OK, TOX_ERR_SEND_MESSAGE_NULL, /** @@ -1224,7 +1231,8 @@ typedef enum TOX_ERR_SEND_MESSAGE { * Attempted to send a zero-length message. */ TOX_ERR_SEND_MESSAGE_EMPTY -} TOX_ERR_SEND_MESSAGE; +}; +typedef uint8_t TOX_ERR_SEND_MESSAGE; /** * Send a text chat message to an online friend. @@ -1363,7 +1371,7 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * ******************************************************************************/ -typedef enum TOX_FILE_KIND { +enum TOX_FILE_KIND { /** * Arbitrary file data. Clients can choose to handle it based on the file name * or magic or any other way they choose. @@ -1386,8 +1394,8 @@ typedef enum TOX_FILE_KIND { * transfer if it matches. */ TOX_FILE_KIND_AVATAR -} TOX_FILE_KIND; - +}; +typedef uint8_t TOX_FILE_KIND; /** * Generates a cryptographic hash of the given data. @@ -1411,7 +1419,7 @@ typedef enum TOX_FILE_KIND { bool tox_hash(uint8_t *hash, uint8_t const *data, size_t length); -typedef enum TOX_FILE_CONTROL { +enum TOX_FILE_CONTROL { /** * Sent by the receiving side to accept a file send request. Also sent after a * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving. @@ -1429,10 +1437,10 @@ typedef enum TOX_FILE_CONTROL { * commands are sent. Also sent by either side to terminate a file transfer. */ TOX_FILE_CONTROL_CANCEL -} TOX_FILE_CONTROL; +}; +typedef uint8_t TOX_FILE_CONTROL; - -typedef enum TOX_ERR_FILE_CONTROL { +enum TOX_ERR_FILE_CONTROL { TOX_ERR_FILE_CONTROL_OK, /** * The friend_number passed did not designate a valid friend. @@ -1459,7 +1467,8 @@ typedef enum TOX_ERR_FILE_CONTROL { * A PAUSE control was sent, but the file transfer was already paused. */ TOX_ERR_FILE_CONTROL_ALREADY_PAUSED -} TOX_ERR_FILE_CONTROL; +}; +typedef uint8_t TOX_ERR_FILE_CONTROL; /** * Sends a file control command to a friend for a given file transfer. @@ -1505,7 +1514,7 @@ void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *us ******************************************************************************/ -typedef enum TOX_ERR_FILE_SEND { +enum TOX_ERR_FILE_SEND { TOX_ERR_FILE_SEND_OK, TOX_ERR_FILE_SEND_NULL, /** @@ -1529,7 +1538,8 @@ typedef enum TOX_ERR_FILE_SEND { * is 256 per friend per direction (sending and receiving). */ TOX_ERR_FILE_SEND_TOO_MANY -} TOX_ERR_FILE_SEND; +}; +typedef uint8_t TOX_ERR_FILE_SEND; /** * Send a file transmission request. @@ -1590,7 +1600,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uin uint8_t const *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); -typedef enum TOX_ERR_FILE_SEND_CHUNK { +enum TOX_ERR_FILE_SEND_CHUNK { TOX_ERR_FILE_SEND_CHUNK_OK, /** * The length parameter was non-zero, but data was NULL. @@ -1614,7 +1624,8 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * the file. Trying to send more will result in no data being sent. */ TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE -} TOX_ERR_FILE_SEND_CHUNK; +}; +typedef uint8_t TOX_ERR_FILE_SEND_CHUNK; /** * Send a chunk of file data to a friend. @@ -1752,7 +1763,7 @@ void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *functi ******************************************************************************/ -typedef enum TOX_ERR_SEND_CUSTOM_PACKET { +enum TOX_ERR_SEND_CUSTOM_PACKET { TOX_ERR_SEND_CUSTOM_PACKET_OK, TOX_ERR_SEND_CUSTOM_PACKET_NULL, /** @@ -1780,8 +1791,8 @@ typedef enum TOX_ERR_SEND_CUSTOM_PACKET { * Send queue size exceeded. */ TOX_ERR_SEND_CUSTOM_PACKET_SENDQ -} TOX_ERR_SEND_CUSTOM_PACKET; - +}; +typedef uint8_t TOX_ERR_SEND_CUSTOM_PACKET; /** * Send a custom lossy packet to a friend. @@ -1880,13 +1891,14 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb void tox_get_dht_id(Tox const *tox, uint8_t *dht_id); -typedef enum TOX_ERR_GET_PORT { +enum TOX_ERR_GET_PORT { TOX_ERR_GET_PORT_OK, /** * The instance was not bound to any port. */ TOX_ERR_GET_PORT_NOT_BOUND -} TOX_ERR_GET_PORT; +}; +typedef uint8_t TOX_ERR_GET_PORT; /** * Return the UDP port this Tox instance is bound to. From 308cf5da6d6f3cccc7834e9a5c8e433c69d6cfdc Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Feb 2015 18:29:32 -0500 Subject: [PATCH 013/101] use bool in is typing callback. --- toxcore/Messenger.c | 4 ++-- toxcore/Messenger.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 4a173de7..fd97c33d 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -929,7 +929,7 @@ void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t m->friend_userstatuschange_userdata = userdata; } -void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, uint8_t, void *), void *userdata) +void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata) { m->friend_typingchange = function; m->friend_typingchange_userdata = userdata; @@ -2043,7 +2043,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) if (data_length != 1) break; - uint8_t typing = data[0]; + _Bool typing = !!data[0]; set_friend_typing(m, i, typing); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index db0777cb..9a5044cd 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -280,7 +280,7 @@ struct Messenger { void *friend_statusmessagechange_userdata; void (*friend_userstatuschange)(struct Messenger *m, uint32_t, uint8_t, void *); void *friend_userstatuschange_userdata; - void (*friend_typingchange)(struct Messenger *m, uint32_t, uint8_t, void *); + void (*friend_typingchange)(struct Messenger *m, uint32_t, _Bool, void *); void *friend_typingchange_userdata; void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *); void *read_receipt_userdata; @@ -664,7 +664,7 @@ void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t /* Set the callback for typing changes. * Function(uint32_t friendnumber, uint8_t is_typing) */ -void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_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(uint32_t friendnumber, uint32_t receipt) From aca41475fa1d2f7ebcc76d84b3dfcbf3c694fb30 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 13 Feb 2015 22:24:39 -0600 Subject: [PATCH 014/101] Put const adjective before type nouns (Done with two applications of "sed -i -r "s/(\\w+) const\\b/const \\1/g" toxcore/tox.*" ) Conflicts: toxcore/tox.c --- toxcore/tox.c | 60 ++++++++++++++--------------- toxcore/tox.h | 104 +++++++++++++++++++++++++------------------------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index a9c7d4dd..43a2c0d9 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -88,7 +88,7 @@ void tox_options_free(struct Tox_Options *options) free(options); } -Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t length, TOX_ERR_NEW *error) +Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t length, TOX_ERR_NEW *error) { if (!logger_get_global()) logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); @@ -177,13 +177,13 @@ void tox_kill(Tox *tox) logger_kill_global(); } -size_t tox_save_size(Tox const *tox) +size_t tox_save_size(const Tox *tox) { const Messenger *m = tox; return messenger_size(m); } -void tox_save(Tox const *tox, uint8_t *data) +void tox_save(const Tox *tox, uint8_t *data) { if (data) { const Messenger *m = tox; @@ -191,7 +191,7 @@ void tox_save(Tox const *tox, uint8_t *data) } } -static int address_to_ip(Messenger *m, char const *address, IP_Port *ip_port, IP_Port *ip_port_v4) +static int address_to_ip(Messenger *m, const char *address, IP_Port *ip_port, IP_Port *ip_port_v4) { if (!addr_parse_ip(address, &ip_port->ip)) { if (m->options.udp_disabled) { /* Disable DNS when udp is disabled. */ @@ -216,7 +216,7 @@ static int address_to_ip(Messenger *m, char const *address, IP_Port *ip_port, IP return 0; } -bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error) +bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) { if (!address || !public_key) { SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL); @@ -243,7 +243,7 @@ bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const * } } -bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, +bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) { if (!address || !public_key) { @@ -272,7 +272,7 @@ bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t con return 1; } -TOX_CONNECTION tox_get_connection_status(Tox const *tox) +TOX_CONNECTION tox_get_connection_status(const Tox *tox) { const Messenger *m = tox; @@ -293,7 +293,7 @@ void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function //TODO } -uint32_t tox_iteration_interval(Tox const *tox) +uint32_t tox_iteration_interval(const Tox *tox) { const Messenger *m = tox; return messenger_run_interval(m); @@ -306,7 +306,7 @@ void tox_iteration(Tox *tox) do_groupchats(m->group_chat_object); } -void tox_self_get_address(Tox const *tox, uint8_t *address) +void tox_self_get_address(const Tox *tox, uint8_t *address) { if (address) { const Messenger *m = tox; @@ -320,13 +320,13 @@ void tox_self_set_nospam(Tox *tox, uint32_t nospam) set_nospam(&(m->fr), nospam); } -uint32_t tox_self_get_nospam(Tox const *tox) +uint32_t tox_self_get_nospam(const Tox *tox) { const Messenger *m = tox; return get_nospam(&(m->fr)); } -void tox_self_get_public_key(Tox const *tox, uint8_t *public_key) +void tox_self_get_public_key(const Tox *tox, uint8_t *public_key) { const Messenger *m = tox; @@ -334,7 +334,7 @@ void tox_self_get_public_key(Tox const *tox, uint8_t *public_key) memcpy(public_key, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); } -void tox_self_get_private_key(Tox const *tox, uint8_t *private_key) +void tox_self_get_private_key(const Tox *tox, uint8_t *private_key) { const Messenger *m = tox; @@ -342,7 +342,7 @@ void tox_self_get_private_key(Tox const *tox, uint8_t *private_key) memcpy(private_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); } -bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET_INFO *error) +bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error) { if (!name && length != 0) { SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL); @@ -362,13 +362,13 @@ bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET } } -size_t tox_self_get_name_size(Tox const *tox) +size_t tox_self_get_name_size(const Tox *tox) { const Messenger *m = tox; return m_get_self_name_size(m); } -void tox_self_get_name(Tox const *tox, uint8_t *name) +void tox_self_get_name(const Tox *tox, uint8_t *name) { if (name) { const Messenger *m = tox; @@ -376,7 +376,7 @@ void tox_self_get_name(Tox const *tox, uint8_t *name) } } -bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, TOX_ERR_SET_INFO *error) +bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error) { if (!status && length != 0) { SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL); @@ -394,13 +394,13 @@ bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, } } -size_t tox_self_get_status_message_size(Tox const *tox) +size_t tox_self_get_status_message_size(const Tox *tox) { const Messenger *m = tox; return m_get_self_statusmessage_size(m); } -void tox_self_get_status_message(Tox const *tox, uint8_t *status) +void tox_self_get_status_message(const Tox *tox, uint8_t *status) { if (status) { const Messenger *m = tox; @@ -414,7 +414,7 @@ void tox_self_set_status(Tox *tox, TOX_STATUS user_status) m_set_userstatus(m, user_status); } -TOX_STATUS tox_self_get_status(Tox const *tox) +TOX_STATUS tox_self_get_status(const Tox *tox) { const Messenger *m = tox; return m_get_self_userstatus(m); @@ -454,7 +454,7 @@ static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error) } } -uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message, size_t length, +uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length, TOX_ERR_FRIEND_ADD *error) { if (!address || !message) { @@ -474,7 +474,7 @@ uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message return UINT32_MAX; } -uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error) +uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error) { if (!public_key) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL); @@ -508,7 +508,7 @@ bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE * return 1; } -uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error) +uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error) { if (!public_key) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL); @@ -527,7 +527,7 @@ uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX return ret; } -bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t *public_key, +bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key, TOX_ERR_FRIEND_GET_PUBLIC_KEY *error) { if (!public_key) { @@ -546,19 +546,19 @@ bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t * return 1; } -bool tox_friend_exists(Tox const *tox, uint32_t friend_number) +bool tox_friend_exists(const Tox *tox, uint32_t friend_number) { const Messenger *m = tox; return m_friend_exists(m, friend_number); } -size_t tox_friend_list_size(Tox const *tox) +size_t tox_friend_list_size(const Tox *tox) { const Messenger *m = tox; return count_friendlist(m); } -void tox_friend_list(Tox const *tox, uint32_t *list) +void tox_friend_list(const Tox *tox, uint32_t *list) { if (list) { const Messenger *m = tox; @@ -567,7 +567,7 @@ void tox_friend_list(Tox const *tox, uint32_t *list) } } -size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { const Messenger *m = tox; int ret = m_get_name_size(m, friend_number); @@ -581,7 +581,7 @@ size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_ return ret; } -bool tox_friend_get_name(Tox const *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error) +bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error) { if (!name) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL); @@ -606,7 +606,7 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user m_callback_friendmessage(m, function, user_data); } -size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { const Messenger *m = tox; int ret = m_get_statusmessage_size(m, friend_number); @@ -620,7 +620,7 @@ size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number return ret; } -bool tox_friend_get_status_message(Tox const *tox, uint32_t friend_number, uint8_t *message, +bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *message, TOX_ERR_FRIEND_QUERY *error) { if (!message) { diff --git a/toxcore/tox.h b/toxcore/tox.h index a3973ae9..2506779e 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -344,7 +344,7 @@ struct Tox_Options { * * This member is ignored (it can be NULL) if proxy_enabled is false. */ - char const *proxy_address; + const char *proxy_address; /** * The port to use to connect to the proxy server. @@ -474,7 +474,7 @@ typedef uint8_t TOX_ERR_NEW; * * @see tox_iteration for the event loop. */ -Tox *tox_new(struct Tox_Options const *options, uint8_t const *data, size_t length, TOX_ERR_NEW *error); +Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t length, TOX_ERR_NEW *error); /** @@ -493,7 +493,7 @@ void tox_kill(Tox *tox); * * @see threading for concurrency implications. */ -size_t tox_save_size(Tox const *tox); +size_t tox_save_size(const Tox *tox); /** * Store all information associated with the tox instance to a byte array. @@ -502,7 +502,7 @@ size_t tox_save_size(Tox const *tox); * Call tox_save_size to find the number of bytes required. If this parameter * is NULL, this function has no effect. */ -void tox_save(Tox const *tox, uint8_t *data); +void tox_save(const Tox *tox, uint8_t *data); /******************************************************************************* @@ -546,7 +546,7 @@ typedef uint8_t TOX_ERR_BOOTSTRAP; * (TOX_PUBLIC_KEY_SIZE bytes). * @return true on success. */ -bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, TOX_ERR_BOOTSTRAP *error); +bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); /** @@ -562,7 +562,7 @@ bool tox_bootstrap(Tox *tox, char const *address, uint16_t port, uint8_t const * * (TOX_PUBLIC_KEY_SIZE bytes). * @return true on success. */ -bool tox_add_tcp_relay(Tox *tox, char const *address, uint16_t port, uint8_t const *public_key, +bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); @@ -592,7 +592,7 @@ typedef uint8_t TOX_CONNECTION; * Return whether we are connected to the DHT. The return value is equal to the * last value received through the `connection_status` callback. */ -TOX_CONNECTION tox_get_connection_status(Tox const *tox); +TOX_CONNECTION tox_get_connection_status(const Tox *tox); /** * The function type for the `connection_status` callback. @@ -620,7 +620,7 @@ void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function * Return the time in milliseconds before tox_iteration() should be called again * for optimal performance. */ -uint32_t tox_iteration_interval(Tox const *tox); +uint32_t tox_iteration_interval(const Tox *tox); /** @@ -646,7 +646,7 @@ void tox_iteration(Tox *tox); * parameter is NULL, this function has no effect. * @see TOX_ADDRESS_SIZE for the address format. */ -void tox_self_get_address(Tox const *tox, uint8_t *address); +void tox_self_get_address(const Tox *tox, uint8_t *address); /** @@ -659,7 +659,7 @@ void tox_self_set_nospam(Tox *tox, uint32_t nospam); /** * Get the 4-byte nospam part of the address. */ -uint32_t tox_self_get_nospam(Tox const *tox); +uint32_t tox_self_get_nospam(const Tox *tox); /** * Copy the Tox Public Key (long term public key) from the Tox object. @@ -667,7 +667,7 @@ uint32_t tox_self_get_nospam(Tox const *tox); * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If * this parameter is NULL, this function has no effect. */ -void tox_self_get_public_key(Tox const *tox, uint8_t *public_key); +void tox_self_get_public_key(const Tox *tox, uint8_t *public_key); /** * Copy the private key from the Tox object. @@ -675,7 +675,7 @@ void tox_self_get_public_key(Tox const *tox, uint8_t *public_key); * @param private_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If * this parameter is NULL, this function has no effect. */ -void tox_self_get_private_key(Tox const *tox, uint8_t *private_key); +void tox_self_get_private_key(const Tox *tox, uint8_t *private_key); /******************************************************************************* @@ -710,7 +710,7 @@ typedef uint8_t TOX_ERR_SET_INFO; * * @return true on success. */ -bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET_INFO *error); +bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error); /** * Return the length of the current nickname as passed to tox_self_set_name. @@ -720,7 +720,7 @@ bool tox_self_set_name(Tox *tox, uint8_t const *name, size_t length, TOX_ERR_SET * * @see threading for concurrency implications. */ -size_t tox_self_get_name_size(Tox const *tox); +size_t tox_self_get_name_size(const Tox *tox); /** * Write the nickname set by tox_self_set_name to a byte array. @@ -734,7 +734,7 @@ size_t tox_self_get_name_size(Tox const *tox); * @param name A valid memory location large enough to hold the nickname. * If this parameter is NULL, the function has no effect. */ -void tox_self_get_name(Tox const *tox, uint8_t *name); +void tox_self_get_name(const Tox *tox, uint8_t *name); /** * Set the client's status message. @@ -743,7 +743,7 @@ void tox_self_get_name(Tox const *tox, uint8_t *name); * length is 0, the status parameter is ignored (it can be NULL), and the * user status is set back to empty. */ -bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, TOX_ERR_SET_INFO *error); +bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error); /** * Return the length of the current status message as passed to @@ -754,7 +754,7 @@ bool tox_self_set_status_message(Tox *tox, uint8_t const *status, size_t length, * * @see threading for concurrency implications. */ -size_t tox_self_get_status_message_size(Tox const *tox); +size_t tox_self_get_status_message_size(const Tox *tox); /** * Write the status message set by tox_self_set_status_message to a byte array. @@ -768,7 +768,7 @@ size_t tox_self_get_status_message_size(Tox const *tox); * @param status A valid memory location large enough to hold the status message. * If this parameter is NULL, the function has no effect. */ -void tox_self_get_status_message(Tox const *tox, uint8_t *status); +void tox_self_get_status_message(const Tox *tox, uint8_t *status); /** @@ -781,7 +781,7 @@ void tox_self_set_status(Tox *tox, TOX_STATUS user_status); /** * Returns the client's user status. */ -TOX_STATUS tox_self_get_status(Tox const *tox); +TOX_STATUS tox_self_get_status(const Tox *tox); /******************************************************************************* @@ -850,7 +850,7 @@ typedef uint8_t TOX_ERR_FRIEND_ADD; * * @return the friend number on success, UINT32_MAX on failure. */ -uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message, size_t length, +uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length, TOX_ERR_FRIEND_ADD *error); @@ -872,7 +872,7 @@ uint32_t tox_friend_add(Tox *tox, uint8_t const *address, uint8_t const *message * @return the friend number on success, UINT32_MAX on failure. * @see tox_friend_add for a more detailed description of friend numbers. */ -uint32_t tox_friend_add_norequest(Tox *tox, uint8_t const *public_key, TOX_ERR_FRIEND_ADD *error); +uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error); enum TOX_ERR_FRIEND_DELETE { @@ -921,7 +921,7 @@ typedef uint8_t TOX_ERR_FRIEND_BY_PUBLIC_KEY; * @return the friend number on success, UINT32_MAX on failure. * @param public_key A byte array containing the Public Key. */ -uint32_t tox_friend_by_public_key(Tox const *tox, uint8_t const *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); +uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { @@ -943,7 +943,7 @@ typedef uint8_t TOX_ERR_FRIEND_GET_PUBLIC_KEY; * * @return true on success. */ -bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t *public_key, +bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key, TOX_ERR_FRIEND_GET_PUBLIC_KEY *error); @@ -951,7 +951,7 @@ bool tox_friend_get_public_key(Tox const *tox, uint32_t friend_number, uint8_t * * Checks if a friend with the given friend number exists and returns true if * it does. */ -bool tox_friend_exists(Tox const *tox, uint32_t friend_number); +bool tox_friend_exists(const Tox *tox, uint32_t friend_number); /** @@ -960,7 +960,7 @@ bool tox_friend_exists(Tox const *tox, uint32_t friend_number); * This function can be used to determine how much memory to allocate for * tox_friend_list. */ -size_t tox_friend_list_size(Tox const *tox); +size_t tox_friend_list_size(const Tox *tox); /** @@ -971,7 +971,7 @@ size_t tox_friend_list_size(Tox const *tox); * @param list A memory region with enough space to hold the friend list. If * this parameter is NULL, this function has no effect. */ -void tox_friend_list(Tox const *tox, uint32_t *list); +void tox_friend_list(const Tox *tox, uint32_t *list); @@ -1007,7 +1007,7 @@ typedef uint8_t TOX_ERR_FRIEND_QUERY; * The return value is equal to the `length` argument received by the last * `friend_name` callback. */ -size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * Write the name of the friend designated by the given friend number to a byte @@ -1023,7 +1023,7 @@ size_t tox_friend_get_name_size(Tox const *tox, uint32_t friend_number, TOX_ERR_ * * @return true on success. */ -bool tox_friend_get_name(Tox const *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error); +bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error); /** * The function type for the `friend_name` callback. @@ -1034,7 +1034,7 @@ bool tox_friend_get_name(Tox const *tox, uint32_t friend_number, uint8_t *name, * @param length A value equal to the return value of * tox_friend_get_name_size. */ -typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, uint8_t const *name, size_t length, void *user_data); +typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data); /** * Set the callback for the `friend_name` event. Pass NULL to unset. @@ -1048,7 +1048,7 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user * Return the length of the friend's status message. If the friend number is * invalid, the return value is SIZE_MAX. */ -size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * Write the name of the friend designated by the given friend number to a byte @@ -1062,7 +1062,7 @@ size_t tox_friend_get_status_message_size(Tox const *tox, uint32_t friend_number * * @param name A valid memory region large enough to store the friend's name. */ -bool tox_friend_get_status_message(Tox const *tox, uint32_t friend_number, uint8_t *message, +bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *message, TOX_ERR_FRIEND_QUERY *error); /** @@ -1075,7 +1075,7 @@ bool tox_friend_get_status_message(Tox const *tox, uint32_t friend_number, uint8 * @param length A value equal to the return value of * tox_friend_get_status_message_size. */ -typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, uint8_t const *message, size_t length, +typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, void *user_data); /** @@ -1093,7 +1093,7 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb * * The status returned is equal to the last status received through the * `friend_status` callback. */ -TOX_STATUS tox_friend_get_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * The function type for the `friend_status` callback. @@ -1124,7 +1124,7 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void * * @return the friend's connection status as it was received through the * `friend_connection_status` event. */ -TOX_CONNECTION tox_friend_get_connection_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * The function type for the `friend_connection_status` callback. @@ -1159,7 +1159,7 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu * @return false if the friend is not typing, or the friend number was * invalid. Inspect the error code to determine which case it is. */ -bool tox_friend_get_typing(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * The function type for the `friend_typing` callback. @@ -1251,7 +1251,7 @@ typedef uint8_t TOX_ERR_SEND_MESSAGE; * incremented by 1 each time a message is sent. If UINT32_MAX messages were * sent, the next message ID is 0. */ -uint32_t tox_send_message(Tox *tox, uint32_t friend_number, uint8_t const *message, size_t length, +uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, TOX_ERR_SEND_MESSAGE *error); @@ -1266,7 +1266,7 @@ uint32_t tox_send_message(Tox *tox, uint32_t friend_number, uint8_t const *messa * * @see tox_send_message for more details. */ -uint32_t tox_send_action(Tox *tox, uint32_t friend_number, uint8_t const *action, size_t length, +uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, TOX_ERR_SEND_MESSAGE *error); @@ -1310,7 +1310,7 @@ void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *us * @param message The message they sent along with the request. * @param length The size of the message byte array. */ -typedef void tox_friend_request_cb(Tox *tox, uint8_t const *public_key, /*uint32_t time_delta, */uint8_t const *message, +typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, /*uint32_t time_delta, */const uint8_t *message, size_t length, void *user_data); /** @@ -1331,7 +1331,7 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void * * @see tox_friend_request_cb for more information on time_delta. */ -typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */uint8_t const *message, +typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */const uint8_t *message, size_t length, void *user_data); /** @@ -1352,7 +1352,7 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void * * @see tox_friend_request_cb for more information on time_delta. */ -typedef void tox_friend_action_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */uint8_t const *action, +typedef void tox_friend_action_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */const uint8_t *action, size_t length, void *user_data); /** @@ -1416,7 +1416,7 @@ typedef uint8_t TOX_FILE_KIND; * * @return true if hash was not NULL. */ -bool tox_hash(uint8_t *hash, uint8_t const *data, size_t length); +bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length); enum TOX_FILE_CONTROL { @@ -1597,7 +1597,7 @@ typedef uint8_t TOX_ERR_FILE_SEND; * number is per friend. File numbers are reused after a transfer terminates. */ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, - uint8_t const *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); + const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); enum TOX_ERR_FILE_SEND_CHUNK { @@ -1640,7 +1640,7 @@ typedef uint8_t TOX_ERR_FILE_SEND_CHUNK; * * @return true on success. */ -bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t const *data, size_t length, +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, const uint8_t *data, size_t length, TOX_ERR_FILE_SEND_CHUNK *error); @@ -1702,7 +1702,7 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi * associated with. */ typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, - uint64_t file_size, uint8_t const *filename, size_t filename_length, void *user_data); + uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); /** * Set the callback for the `file_receive` event. Pass NULL to unset. @@ -1734,7 +1734,7 @@ void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *us * @param length The length of the received chunk. */ typedef void tox_file_receive_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, - uint8_t const *data, size_t length, void *user_data); + const uint8_t *data, size_t length, void *user_data); /** * Set the callback for the `file_receive_chunk` event. Pass NULL to unset. @@ -1814,7 +1814,7 @@ typedef uint8_t TOX_ERR_SEND_CUSTOM_PACKET; * * @return true on success. */ -bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, +bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, TOX_ERR_SEND_CUSTOM_PACKET *error); /** @@ -1824,7 +1824,7 @@ bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, uint8_t const *data * @param data A byte array containing the received packet data. * @param length The length of the packet data byte array. */ -typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, +typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data); /** @@ -1849,7 +1849,7 @@ void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *func * * @return true on success. */ -bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, +bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, TOX_ERR_SEND_CUSTOM_PACKET *error); /** @@ -1859,7 +1859,7 @@ bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, uint8_t const *d * @param data A byte array containing the received packet data. * @param length The length of the packet data byte array. */ -typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, uint8_t const *data, size_t length, +typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data); /** @@ -1888,7 +1888,7 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb * @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this * parameter is NULL, this function has no effect. */ -void tox_get_dht_id(Tox const *tox, uint8_t *dht_id); +void tox_get_dht_id(const Tox *tox, uint8_t *dht_id); enum TOX_ERR_GET_PORT { @@ -1903,13 +1903,13 @@ typedef uint8_t TOX_ERR_GET_PORT; /** * Return the UDP port this Tox instance is bound to. */ -uint16_t tox_get_udp_port(Tox const *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error); /** * Return the TCP port this Tox instance is bound to. This is only relevant if * the instance is acting as a TCP relay. */ -uint16_t tox_get_tcp_port(Tox const *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); #ifdef __cplusplus From c037aefe9da822ca3e54ba018e5693fa71372128 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 19 Feb 2015 16:54:49 -0500 Subject: [PATCH 015/101] Typing and status functions implemented. --- toxcore/Messenger.c | 2 +- toxcore/Messenger.h | 2 +- toxcore/tox.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fd97c33d..ced02a12 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -806,7 +806,7 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing) return 0; } -uint8_t m_get_istyping(const Messenger *m, int32_t friendnumber) +int m_get_istyping(const Messenger *m, int32_t friendnumber) { if (friend_not_valid(m, friendnumber)) return -1; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 9a5044cd..4e709f64 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -616,7 +616,7 @@ 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); +int 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). diff --git a/toxcore/tox.c b/toxcore/tox.c index a9c7d4dd..6aaed15f 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -646,3 +646,43 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb * Messenger *m = tox; m_callback_statusmessage(m, function, user_data); } + +TOX_STATUS tox_friend_get_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +{ + const Messenger *m = tox; + + int ret = m_get_userstatus(m, friend_number); + + if (ret == USERSTATUS_INVALID) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return TOX_STATUS_INVALID; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return ret; +} + +void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_userstatus(m, function, user_data); +} + +bool tox_friend_get_typing(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +{ + const Messenger *m = tox; + int ret = m_get_istyping(m, friend_number); + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return !!ret; +} + +void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_typingchange(m, function, user_data); +} From c87da9203e09cf1c7e0f19fc397808424fdaeea2 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 19 Feb 2015 20:51:19 -0500 Subject: [PATCH 016/101] Tox connection function and callback should now work as expected. Changes in Messenger to call the callback every time the connection type changes from TCP to UDP. --- toxcore/Messenger.c | 36 +++++++++++++++++++++++++++++++++--- toxcore/Messenger.h | 12 ++++++++++-- toxcore/tox.c | 26 ++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ced02a12..11da5951 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -358,7 +358,19 @@ int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber) if (friend_not_valid(m, friendnumber)) return -1; - return m->friendlist[friendnumber].status == FRIEND_ONLINE; + if (m->friendlist[friendnumber].status == FRIEND_ONLINE) { + uint8_t direct_connected = 0; + crypto_connection_status(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), &direct_connected); + + if (direct_connected) { + return CONNECTION_UDP; + } else { + return CONNECTION_TCP; + } + } else { + return CONNECTION_NONE; + } } int m_friend_exists(const Messenger *m, int32_t friendnumber) @@ -969,6 +981,23 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, uint32_ m->avatar_data_recv_userdata = userdata; } +static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber) +{ + int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp; + + int ret = m_get_friend_connectionstatus(m, friendnumber); + + if (ret == -1) + return; + + if (last_connection_udp_tcp != ret) { + if (m->friend_connectionstatuschange) + m->friend_connectionstatuschange(m, friendnumber, ret, m->friend_connectionstatuschange_userdata); + } + + m->friendlist[friendnumber].last_connection_udp_tcp = ret; +} + static void break_files(const Messenger *m, int32_t friendnumber); static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status) { @@ -988,8 +1017,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui m->friendlist[friendnumber].status = status; - if (m->friend_connectionstatuschange) - m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata); + check_friend_tcp_udp(m, friendnumber); if (m->friend_connectionstatuschange_internal) m->friend_connectionstatuschange_internal(m, friendnumber, is_online, @@ -2316,6 +2344,8 @@ void do_friends(Messenger *m) if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) { send_relays(m, i); } + + check_friend_tcp_udp(m, i); } } } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 4e709f64..da1bbe9f 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -114,6 +114,12 @@ enum { #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. */ @@ -215,6 +221,7 @@ typedef struct { 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]; struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; @@ -372,8 +379,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); diff --git a/toxcore/tox.c b/toxcore/tox.c index b166d151..db100459 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -647,7 +647,7 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb * m_callback_statusmessage(m, function, user_data); } -TOX_STATUS tox_friend_get_status(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { const Messenger *m = tox; @@ -668,10 +668,32 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void * m_callback_userstatus(m, function, user_data); } -bool tox_friend_get_typing(Tox const *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +{ + const Messenger *m = tox; + + int ret = m_get_friend_connectionstatus(m, friend_number); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); + return TOX_CONNECTION_NONE; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); + return ret; +} + +void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_connectionstatus(m, function, user_data); +} + +bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { const Messenger *m = tox; int ret = m_get_istyping(m, friend_number); + if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); return 0; From 41446f61e36844255f443f0094bb707abfddf7ed Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 20 Feb 2015 17:24:24 -0500 Subject: [PATCH 017/101] Implemented message send functions in public api. Internal message functions now return better error codes. --- toxcore/Messenger.c | 44 ++++++++++++++++-------- toxcore/Messenger.h | 24 +++++++------ toxcore/tox.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index a9d5e6a1..e5298b31 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -366,7 +366,8 @@ static int do_receipts(Messenger *m, int32_t friendnumber) while (receipts) { struct Receipts *temp_r = receipts->next; - if (cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), receipts->packet_num) == -1) + if (cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), receipts->packet_num) == -1) break; if (m->read_receipt) @@ -450,15 +451,25 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) return 1; } - -static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, - uint8_t packet_id) +/* Send a packet_id message. + * + * 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 0 if success. + */ +static int send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, + uint8_t packet_id, uint32_t *message_id) { if (friend_not_valid(m, friendnumber)) - return 0; + return -1; - if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) - return 0; + if (length >= MAX_CRYPTO_DATA_SIZE) + return -2; + + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -3; uint8_t packet[length + 1]; packet[0] = packet_id; @@ -466,10 +477,11 @@ static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const u if (length != 0) memcpy(packet + 1, message, length); - int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0); + int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0); if (packet_num == -1) - return 0; + return -4; uint32_t msg_id = ++m->friendlist[friendnumber].message_id; @@ -478,7 +490,11 @@ static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const u } add_receipt(m, friendnumber, packet_num, msg_id); - return msg_id; + + if (message_id) + *message_id = msg_id; + + return 0; } /* Send a text chat message to an online friend. @@ -486,9 +502,9 @@ static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const u * return the message id if packet was successfully put into the send queue. * return 0 if it was not. */ -uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length) +int m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, uint32_t *message_id) { - return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE); + return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE, message_id); } /* Send an action to an online friend. @@ -496,9 +512,9 @@ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *messag * return the message id if packet was successfully put into the send queue. * return 0 if it was not. */ -uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length) +int m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length, uint32_t *message_id) { - return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION); + return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION, message_id); } /* Send a name packet to friendnumber. diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 0a613c0b..4e011a57 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -403,23 +403,27 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber); /* Send a text chat message 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 0 if success. * - * You will want to retain the return value, it will be passed to your read_receipt callback - * if one is received. + * 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); +int m_sendmessage(Messenger *m, int32_t friendnumber, 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. + * 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 0 if success. * - * You will want to retain the return value, it will be passed to your read_receipt callback - * if one is received. + * the value in message_id will be passed to your read_receipt callback when the other receives the message. */ -uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length); +int m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length, uint32_t *message_id); /* Set the name and name_length of a friend. * name must be a string of maximum MAX_NAME_LENGTH length. diff --git a/toxcore/tox.c b/toxcore/tox.c index db100459..54850d69 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -708,3 +708,87 @@ void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void * Messenger *m = tox; m_callback_typingchange(m, function, user_data); } + +bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error) +{ + Messenger *m = tox; + + if (m_set_usertyping(m, friend_number, is_typing) == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK); + return 1; +} + +static void set_message_error(int ret, TOX_ERR_SEND_MESSAGE *error) +{ + switch (ret) { + case 0: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_OK); + break; + + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_FRIEND_NOT_FOUND); + break; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_TOO_LONG); + break; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_FRIEND_NOT_CONNECTED); + break; + + case -4: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_SENDQ); + break; + } +} + +uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, + TOX_ERR_SEND_MESSAGE *error) +{ + if (!message) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_NULL); + return 0; + } + + if (!length) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_EMPTY); + return 0; + } + + Messenger *m = tox; + uint32_t message_id = 0; + set_message_error(m_sendmessage(m, friend_number, message, length, &message_id), error); + return message_id; +} + +uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, + TOX_ERR_SEND_MESSAGE *error) +{ + if (!action) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_NULL); + return 0; + } + + if (!length) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_EMPTY); + return 0; + } + + Messenger *m = tox; + uint32_t message_id = 0; + set_message_error(m_sendaction(m, friend_number, action, length, &message_id), error); + return message_id; +} + +void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_read_receipt(m, function, user_data); +} + + From ca21569a9d0ec4c1a05e7fede61359d158c194f5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 20 Feb 2015 18:17:32 -0500 Subject: [PATCH 018/101] Implemented callbacks. --- toxcore/tox.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/toxcore/tox.c b/toxcore/tox.c index 54850d69..3f344ffe 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -791,4 +791,21 @@ void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *us m_callback_read_receipt(m, function, user_data); } +void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_friendrequest(m, function, user_data); +} + +void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_friendmessage(m, function, user_data); +} + +void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void *user_data) +{ + Messenger *m = tox; + m_callback_action(m, function, user_data); +} From 8fa8e9dcd798540bf539d502d0dbba71184f7489 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 24 Feb 2015 19:39:19 -0500 Subject: [PATCH 019/101] Remove avatar stuff from Messenger. The new api sees avatars as a different type of file transfer. --- toxcore/Messenger.c | 486 -------------------------------------------- toxcore/Messenger.h | 213 ------------------- 2 files changed, 699 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index e5298b31..863259ac 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -39,7 +39,6 @@ static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, uint32_t length, uint8_t congestion_control); -static int send_avatar_data_control(const Messenger *m, const uint32_t friendnumber, uint8_t op); // friend_not_valid determines if the friendnumber passed is valid in the Messenger object static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) @@ -208,10 +207,6 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta id_copy(m->friendlist[i].real_pk, real_pk); m->friendlist[i].statusmessage_length = 0; m->friendlist[i].userstatus = USERSTATUS_NONE; - m->friendlist[i].avatar_info_sent = 0; - m->friendlist[i].avatar_recv_data = NULL; - m->friendlist[i].avatar_send_data.bytes_sent = 0; - m->friendlist[i].avatar_send_data.last_reset = 0; m->friendlist[i].is_typing = 0; m->friendlist[i].message_id = 0; friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, @@ -397,7 +392,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber) if (m->friendlist[friendnumber].status == FRIEND_ONLINE) remove_online_friend(m, friendnumber); - free(m->friendlist[friendnumber].avatar_recv_data); clear_receipts(m, friendnumber); remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); @@ -656,149 +650,6 @@ int m_set_userstatus(Messenger *m, uint8_t status) return 0; } -int m_unset_avatar(Messenger *m) -{ - if (m->avatar_data != NULL) - free(m->avatar_data); - - m->avatar_data = NULL; - m->avatar_data_length = 0; - m->avatar_format = AVATAR_FORMAT_NONE; - memset(m->avatar_hash, 0, AVATAR_HASH_LENGTH); - - uint32_t i; - - for (i = 0; i < m->numfriends; ++i) - m->friendlist[i].avatar_info_sent = 0; - - return 0; -} - -int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length) -{ - if (format == AVATAR_FORMAT_NONE) { - m_unset_avatar(m); - return 0; - } - - if (length > AVATAR_MAX_DATA_LENGTH || length == 0) - return -1; - - if (data == NULL) - return -1; - - uint8_t *tmp = realloc(m->avatar_data, length); - - if (tmp == NULL) - return -1; - - m->avatar_format = format; - m->avatar_data = tmp; - m->avatar_data_length = length; - memcpy(m->avatar_data, data, length); - - m_avatar_hash(m->avatar_hash, m->avatar_data, m->avatar_data_length); - - uint32_t i; - - for (i = 0; i < m->numfriends; ++i) - m->friendlist[i].avatar_info_sent = 0; - - return 0; -} - -int m_get_self_avatar(const Messenger *m, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, - uint8_t *hash) -{ - if (format) - *format = m->avatar_format; - - if (length) - *length = m->avatar_data_length; - - if (hash) - memcpy(hash, m->avatar_hash, AVATAR_HASH_LENGTH); - - if (buf != NULL && maxlen > 0) { - if (m->avatar_data_length <= maxlen) - memcpy(buf, m->avatar_data, m->avatar_data_length); - else - return -1; - } - - return 0; -} - -int m_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen) -{ - if (hash == NULL) - return -1; - - return crypto_hash_sha256(hash, data, datalen); -} - -int m_avatar_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen) -{ - return m_hash(hash, data, datalen); -} - -int m_request_avatar_info(const Messenger *m, const int32_t friendnumber) -{ - if (friend_not_valid(m, friendnumber)) - return -1; - - if (write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_INFO_REQ, 0, 0, 0)) - return 0; - else - return -1; -} - -int m_send_avatar_info(const Messenger *m, const int32_t friendnumber) -{ - if (friend_not_valid(m, friendnumber)) - return -1; - - uint8_t data[sizeof(uint8_t) + AVATAR_HASH_LENGTH]; - data[0] = m->avatar_format; - memcpy(data + 1, m->avatar_hash, AVATAR_HASH_LENGTH); - - if (write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_INFO, data, sizeof(data), 0)) - return 0; - else - return -1; -} - -int m_request_avatar_data(const Messenger *m, const int32_t friendnumber) -{ - if (friend_not_valid(m, friendnumber)) - return -1; - - AVATAR_RECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data; - - if (avrd == NULL) { - avrd = calloc(sizeof(AVATAR_RECEIVEDATA), 1); - - if (avrd == NULL) - return -1; - - avrd->started = 0; - m->friendlist[friendnumber].avatar_recv_data = avrd; - } - - if (avrd->started) { - LOGGER_DEBUG("Resetting already started data request. " - "friendnumber == %u", friendnumber); - } - - avrd->started = 0; - avrd->bytes_received = 0; - avrd->total_length = 0; - avrd->format = AVATAR_FORMAT_NONE; - - return send_avatar_data_control(m, friendnumber, AVATAR_DATACONTROL_REQ); -} - - /* return the size of friendnumber's user status. * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH. */ @@ -1021,20 +872,6 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess m->friend_connectionstatuschange_internal_userdata = userdata; } -void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, void *), - void *userdata) -{ - m->avatar_info_recv = function; - m->avatar_info_recv_userdata = userdata; -} - -void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, uint8_t *, uint8_t *, - uint32_t, void *), void *userdata) -{ - m->avatar_data_recv = function; - m->avatar_data_recv_userdata = userdata; -} - static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber) { int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp; @@ -1646,9 +1483,6 @@ Messenger *new_messenger(Messenger_Options *options) m->net = new_networking(ip, TOX_PORT_DEFAULT); } - m->avatar_format = AVATAR_FORMAT_NONE; - m->avatar_data = NULL; - if (m->net == NULL) { free(m); return NULL; @@ -1714,11 +1548,9 @@ void kill_messenger(Messenger *m) kill_networking(m->net); for (i = 0; i < m->numfriends; ++i) { - free(m->friendlist[i].avatar_recv_data); clear_receipts(m, i); } - free(m->avatar_data); free(m->friendlist); free(m); } @@ -1752,293 +1584,16 @@ static int handle_status(void *object, int i, uint8_t status) m->friendlist[i].userstatus_sent = 0; m->friendlist[i].statusmessage_sent = 0; m->friendlist[i].user_istyping_sent = 0; - m->friendlist[i].avatar_info_sent = 0; m->friendlist[i].ping_lastrecv = temp_time; } else { /* Went offline. */ if (m->friendlist[i].status == FRIEND_ONLINE) { set_friend_status(m, i, FRIEND_CONFIRMED); } - - /* Clear avatar transfer state */ - if (m->friendlist[i].avatar_recv_data) { - free(m->friendlist[i].avatar_recv_data); - m->friendlist[i].avatar_recv_data = NULL; - } } return 0; } - -/* Sends an avatar data control packet to the peer. Usually to return status - * values or request data. - */ -static int send_avatar_data_control(const Messenger *m, const uint32_t friendnumber, - uint8_t op) -{ - int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_DATA_CONTROL, - &op, sizeof(op), 0); - LOGGER_DEBUG("friendnumber = %u, op = %u, ret = %d", - friendnumber, op, ret); - return ret ? 0 : -1; -} - - -static int handle_avatar_data_control(Messenger *m, uint32_t friendnumber, - uint8_t *data, uint32_t data_length) -{ - if (data_length != 1) { - LOGGER_DEBUG("Error: PACKET_ID_AVATAR_DATA_CONTROL with bad " - "data_length = %u, friendnumber = %u", - data_length, friendnumber); - send_avatar_data_control(m, friendnumber, AVATAR_DATACONTROL_ERROR); - return -1; /* Error */ - } - - LOGGER_DEBUG("friendnumber = %u, op = %u", friendnumber, data[0]); - - switch (data[0]) { - case AVATAR_DATACONTROL_REQ: { - - /* Check data transfer limits for this friend */ - AVATAR_SENDDATA *const avsd = &(m->friendlist[friendnumber].avatar_send_data); - - if (avsd->bytes_sent >= AVATAR_DATA_TRANSFER_LIMIT) { - /* User reached data limit. Check timeout */ - uint64_t now = unix_time(); - - if (avsd->last_reset > 0 - && (avsd->last_reset + AVATAR_DATA_TRANSFER_TIMEOUT < now)) { - avsd->bytes_sent = 0; - avsd->last_reset = now; - } else { - /* Friend still rate-limitted. Send an error and stops. */ - LOGGER_DEBUG("Avatar data transfer limit reached. " - "friendnumber = %u", friendnumber); - send_avatar_data_control(m, friendnumber, AVATAR_DATACONTROL_ERROR); - return 0; - } - } - - /* Start the transmission with a DATA_START message. Format: - * uint8_t format - * uint8_t hash[AVATAR_HASH_LENGTH] - * uint32_t total_length - */ - LOGGER_DEBUG("Sending start msg to friend number %u. " - "m->avatar_format = %u, m->avatar_data_length = %u", - friendnumber, m->avatar_format, m->avatar_data_length); - uint8_t start_data[1 + AVATAR_HASH_LENGTH + sizeof(uint32_t)]; - uint32_t avatar_len = htonl(m->avatar_data_length); - - start_data[0] = m->avatar_format; - memcpy(start_data + 1, m->avatar_hash, AVATAR_HASH_LENGTH); - memcpy(start_data + 1 + AVATAR_HASH_LENGTH, &avatar_len, sizeof(uint32_t)); - - avsd->bytes_sent += sizeof(start_data); /* For rate limit */ - - int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_DATA_START, - start_data, sizeof(start_data), 0); - - if (!ret) { - /* Something went wrong, try to signal the error so the friend - * can clear up the state. */ - send_avatar_data_control(m, friendnumber, AVATAR_DATACONTROL_ERROR); - return 0; - } - - /* User have no avatar data, nothing more to do. */ - if (m->avatar_format == AVATAR_FORMAT_NONE) - return 0; - - /* Send the actual avatar data. */ - uint32_t offset = 0; - - while (offset < m->avatar_data_length) { - uint32_t chunk_len = m->avatar_data_length - offset; - - if (chunk_len > AVATAR_DATA_MAX_CHUNK_SIZE) - chunk_len = AVATAR_DATA_MAX_CHUNK_SIZE; - - uint8_t chunk[AVATAR_DATA_MAX_CHUNK_SIZE]; - memcpy(chunk, m->avatar_data + offset, chunk_len); - offset += chunk_len; - avsd->bytes_sent += chunk_len; /* For rate limit */ - - int ret = write_cryptpacket_id(m, friendnumber, - PACKET_ID_AVATAR_DATA_PUSH, - chunk, chunk_len, 0); - - if (!ret) { - LOGGER_DEBUG("write_cryptpacket_id failed. ret = %d, " - "friendnumber = %u, offset = %u", - ret, friendnumber, offset); - send_avatar_data_control(m, friendnumber, AVATAR_DATACONTROL_ERROR); - return -1; - } - } - - return 0; - } - - case AVATAR_DATACONTROL_ERROR: { - if (m->friendlist[friendnumber].avatar_recv_data) { - /* We were receiving the data, sender detected an error - (eg. changing avatar) and asked us to stop. */ - free(m->friendlist[friendnumber].avatar_recv_data); - m->friendlist[friendnumber].avatar_recv_data = NULL; - } - - return 0; - } - } - - return -1; -} - - -static int handle_avatar_data_start(Messenger *m, uint32_t friendnumber, - uint8_t *data, uint32_t data_length) -{ - LOGGER_DEBUG("data_length = %u, friendnumber = %u", data_length, friendnumber); - - if (data_length != 1 + AVATAR_HASH_LENGTH + sizeof(uint32_t)) { - LOGGER_DEBUG("Invalid msg length = %u, friendnumber = %u", - data_length, friendnumber); - return -1; - } - - AVATAR_RECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data; - - if (avrd == NULL) { - LOGGER_DEBUG("Received an unrequested DATA_START, friendnumber = %u", - friendnumber); - return -1; - } - - if (avrd->started) { - /* Already receiving data from this friend. Must be an error - * or an malicious request, because we zeroed the started bit - * when we requested the data. */ - LOGGER_DEBUG("Received an unrequested duplicated DATA_START, " - "friendnumber = %u", friendnumber); - return -1; - } - - /* Copy data from message to our control structure */ - avrd->started = 1; - avrd->format = data[0]; - memcpy(avrd->hash, data + 1, AVATAR_HASH_LENGTH); - uint32_t tmp_len; - memcpy(&tmp_len, data + 1 + AVATAR_HASH_LENGTH, sizeof(uint32_t)); - avrd->total_length = ntohl(tmp_len); - avrd->bytes_received = 0; - - LOGGER_DEBUG("friendnumber = %u, avrd->format = %u, " - "avrd->total_length = %u, avrd->bytes_received = %u", - friendnumber, avrd->format, avrd->total_length, - avrd->bytes_received); - - if (avrd->total_length > AVATAR_MAX_DATA_LENGTH) { - /* Invalid data length. Stops. */ - LOGGER_DEBUG("Error: total_length > MAX_AVATAR_DATA_LENGTH, " - "friendnumber = %u", friendnumber); - free(avrd); - avrd = NULL; - m->friendlist[friendnumber].avatar_recv_data = NULL; - return 0; - } - - if (avrd->format == AVATAR_FORMAT_NONE || avrd->total_length == 0) { - /* No real data to receive. Run callback function and finish. */ - LOGGER_DEBUG("format == NONE, friendnumber = %u", friendnumber); - - if (m->avatar_data_recv) { - memset(avrd->hash, 0, AVATAR_HASH_LENGTH); - (m->avatar_data_recv)(m, friendnumber, avrd->format, avrd->hash, - NULL, 0, m->avatar_data_recv_userdata); - } - - free(avrd); - avrd = NULL; - m->friendlist[friendnumber].avatar_recv_data = NULL; - return 0; - } - - /* Waits for more data to be received */ - return 0; -} - - -static int handle_avatar_data_push(Messenger *m, uint32_t friendnumber, - uint8_t *data, uint32_t data_length) -{ - LOGGER_DEBUG("friendnumber = %u, data_length = %u", friendnumber, data_length); - - AVATAR_RECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data; - - if (avrd == NULL) { - /* No active transfer. It must be an error or a malicious request, - * because we set the avatar_recv_data on the first DATA_START. */ - LOGGER_DEBUG("Error: avrd == NULL, friendnumber = %u", friendnumber); - return -1; /* Error */ - } - - if (avrd->started == 0) { - /* Receiving data for a non-started request. Must be an error - * or an malicious request. */ - LOGGER_DEBUG("Received an data push for a yet non started data " - "request. friendnumber = %u", friendnumber); - return -1; /* Error */ - } - - uint32_t new_length = avrd->bytes_received + data_length; - - if (new_length > avrd->total_length - || new_length >= AVATAR_MAX_DATA_LENGTH) { - /* Invalid data length due to error or malice. Stops. */ - LOGGER_DEBUG("Invalid data length. friendnumber = %u, " - "new_length = %u, avrd->total_length = %u", - friendnumber, new_length, avrd->total_length); - free(avrd); - m->friendlist[friendnumber].avatar_recv_data = NULL; - return 0; - } - - memcpy(avrd->data + avrd->bytes_received, data, data_length); - avrd->bytes_received += data_length; - - if (avrd->bytes_received == avrd->total_length) { - LOGGER_DEBUG("All data received. friendnumber = %u", friendnumber); - - /* All data was received. Check if the hashes match. It the - * requester's responsability to do this. The sender may have done - * anything with its avatar data between the DATA_START and now. - */ - uint8_t cur_hash[AVATAR_HASH_LENGTH]; - m_avatar_hash(cur_hash, avrd->data, avrd->bytes_received); - - if (memcmp(cur_hash, avrd->hash, AVATAR_HASH_LENGTH) == 0) { - /* Avatar successfuly received! */ - if (m->avatar_data_recv) { - (m->avatar_data_recv)(m, friendnumber, avrd->format, cur_hash, - avrd->data, avrd->bytes_received, m->avatar_data_recv_userdata); - } - } else { - LOGGER_DEBUG("Avatar hash error. friendnumber = %u", friendnumber); - } - - free(avrd); - m->friendlist[friendnumber].avatar_recv_data = NULL; - return 0; - } - - /* Waits for more data to be received */ - return 0; -} - - - static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) { if (len == 0) @@ -2178,42 +1733,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; } - case PACKET_ID_AVATAR_INFO_REQ: { - /* Send our avatar information */ - m_send_avatar_info(m, i); - break; - } - - case PACKET_ID_AVATAR_INFO: { - if (m->avatar_info_recv) { - /* - * A malicious user may send an incomplete avatar info message. - * Check if it have the correct size for the format: - * [1 uint8_t: avatar format] [32 uint8_t: hash] - */ - if (data_length == AVATAR_HASH_LENGTH + 1) { - (m->avatar_info_recv)(m, i, data[0], data + 1, m->avatar_info_recv_userdata); - } - } - - break; - } - - case PACKET_ID_AVATAR_DATA_CONTROL: { - handle_avatar_data_control(m, i, data, data_length); - break; - } - - case PACKET_ID_AVATAR_DATA_START: { - handle_avatar_data_start(m, i, data, data_length); - break; - } - - case PACKET_ID_AVATAR_DATA_PUSH: { - handle_avatar_data_push(m, i, data, data_length); - break; - } - case PACKET_ID_INVITE_GROUPCHAT: { if (data_length == 0) break; @@ -2362,11 +1881,6 @@ void do_friends(Messenger *m) m->friendlist[i].userstatus_sent = 1; } - if (m->friendlist[i].avatar_info_sent == 0) { - if (m_send_avatar_info(m, i) == 0) - m->friendlist[i].avatar_info_sent = 1; - } - if (m->friendlist[i].user_istyping_sent == 0) { if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) m->friendlist[i].user_istyping_sent = 1; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 4e011a57..48235900 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -33,8 +33,6 @@ #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)) @@ -47,11 +45,6 @@ #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_MESSAGE 64 #define PACKET_ID_ACTION 65 #define PACKET_ID_MSI 69 @@ -112,14 +105,6 @@ enum { /* 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, @@ -138,42 +123,6 @@ 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; - - struct File_Transfers { uint64_t size; uint64_t transferred; @@ -217,7 +166,6 @@ typedef struct { 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; @@ -230,9 +178,6 @@ typedef struct { struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; 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, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object); void *object; @@ -269,11 +214,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; @@ -305,10 +245,6 @@ struct Messenger { void *friend_connectionstatuschange_userdata; 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, uint32_t, uint8_t, uint8_t *, void *); - void *avatar_data_recv_userdata; - void (*avatar_data_recv)(struct Messenger *m, uint32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *); void *group_chat_object; /* Set by new_groupchats()*/ void (*group_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t); @@ -503,113 +439,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. */ @@ -702,48 +531,6 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess 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, uint32_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. - * - */ -void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, uint32_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, uint32_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, uint32_t, uint8_t, uint8_t *, uint8_t *, - uint32_t, void *), void *userdata); - - - /**********GROUP CHATS************/ /* Set the callback for group invites. From d83efd35dd342da7f5b0f4b6e11ffd943d7f3c63 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 24 Feb 2015 20:29:01 -0500 Subject: [PATCH 020/101] Ported some of the code in testing/ to the new api. --- testing/Makefile.inc | 15 - testing/Messenger_test.c | 12 +- testing/dns3_test.c | 4 +- testing/irc_syncbot.c | 16 +- testing/nTox.c | 133 +++---- testing/test_avatars.c | 755 --------------------------------------- testing/tox_shell.c | 32 +- testing/tox_sync.c | 28 +- 8 files changed, 116 insertions(+), 879 deletions(-) delete mode 100644 testing/test_avatars.c diff --git a/testing/Makefile.inc b/testing/Makefile.inc index 8b93c8ac..fda99a89 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc @@ -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 diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 42cadf73..27216107 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -56,17 +56,17 @@ #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, 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_sendmessage(m, friendnumber, (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 +79,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; @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) getname(m, num, name); printf("%s\n", name); - m_sendmessage(m, num, (uint8_t *)"Test", 5); + m_sendmessage(m, num, (uint8_t *)"Test", 5, 0); do_messenger(m); c_sleep(30); FILE *file = fopen("Save.bak", "wb"); diff --git a/testing/dns3_test.c b/testing/dns3_test.c index 7052aae7..1f6c6a12 100644 --- a/testing/dns3_test.c +++ b/testing/dns3_test.c @@ -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]); } diff --git a/testing/irc_syncbot.c b/testing/irc_syncbot.c index f7486115..df9e964c 100644 --- a/testing/irc_syncbot.c +++ b/testing/irc_syncbot.c @@ -89,7 +89,7 @@ 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, const uint8_t *message, size_t length, void *userdata) { if (length == 1 && *message == 'c') { if (tox_del_groupchat(tox, current_group) == 0) @@ -203,7 +203,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 +215,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, ©_groupmessage, 0); @@ -228,7 +228,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 +239,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 +342,7 @@ int main(int argc, char *argv[]) } } - tox_do(tox); + tox_iteration(tox); usleep(1000 * 50); } diff --git a/testing/nTox.c b/testing/nTox.c index 329191d7..ff419c9a 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -105,7 +105,7 @@ 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; @@ -179,19 +179,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 +210,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 +250,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 +265,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 +348,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) { - sprintf(numstring, "[i] Added friend as %d.", num); - save_data(m); - } else - sprintf(numstring, "[i] Unknown error %i.", num); + 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); break; } new_lines(numstring); } else if (inpt_command == 'd') { - tox_do(m); + tox_iteration(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_send_message(m, num, (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 +420,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 +437,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 +449,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 +485,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 +612,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_send_message(m, friendnumber, (uint8_t *)line, strlen(line), NULL); if (res == 0) { char sss[128]; @@ -863,20 +873,20 @@ 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, const uint8_t *string, size_t length, void *userdata) { /* ensure null termination */ uint8_t null_string[length + 1]; @@ -885,7 +895,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 +911,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 +929,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 +946,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 +954,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,7 +970,7 @@ static int save_data(Tox *m) } int res = 1; - size_t size = tox_size(m); + size_t size = tox_save_size(m); uint8_t data[size]; tox_save(m, data); @@ -977,13 +987,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; @@ -1176,7 +1183,7 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *dat 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 +1221,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,19 +1238,20 @@ 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); @@ -1263,7 +1271,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 +1283,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 +1297,7 @@ int main(int argc, char *argv[]) while (1) { if (on == 0) { - if (tox_isconnected(m)) { + if (tox_get_connection_status(m)) { new_lines("[i] connected to DHT"); on = 1; } else { @@ -1296,15 +1305,13 @@ 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_iteration(m); do_refresh(); int c = timeout_getch(m); @@ -1320,7 +1327,7 @@ 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); } } diff --git a/testing/test_avatars.c b/testing/test_avatars.c deleted file mode 100644 index b4adc48f..00000000 --- a/testing/test_avatars.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * A bot to test Tox avatars - * - * Usage: ./test_avatars - * - * 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: ".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/.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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -/* 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 \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; -} diff --git a/testing/tox_shell.c b/testing/tox_shell.c index 738d8616..5198d224 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -45,15 +45,15 @@ #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, uint8_t 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, const uint8_t *string, size_t length, void *userdata) { int master = *((int *)userdata); write(master, string, length); @@ -62,7 +62,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 +94,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 +109,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 +125,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 +136,22 @@ int main(int argc, char *argv[]) uint8_t notconnected = 1; while (1) { - if (tox_isconnected(tox) && notconnected) { + if (tox_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_send_message(tox, num, buf, ret, 0); } - tox_do(tox); + tox_iteration(tox); c_sleep(1); } diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 8b64b6ca..77f75c36 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -192,9 +192,9 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *dat 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, uint8_t status, void *userdata) { - if (status == 1) + if (status) printf("\nOther went online.\n"); else printf("\nOther went offline.\n"); @@ -202,7 +202,7 @@ void print_online(Tox *tox, int friendnumber, uint8_t status, void *userdata) 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 +214,15 @@ int main(int argc, char *argv[]) exit(0); } - Tox *tox = tox_new(0); + Tox *tox = tox_new(0, 0, 0, 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_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 +230,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 +246,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 +260,12 @@ int main(int argc, char *argv[]) uint8_t notconnected = 1; while (1) { - if (tox_isconnected(tox) && notconnected) { + if (tox_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) { @@ -291,7 +291,7 @@ int main(int argc, char *argv[]) } send_filesenders(tox); - tox_do(tox); + tox_iteration(tox); c_sleep(1); } From 837d4698bbe4ae8e6f8242259516d23240195195 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 25 Feb 2015 19:50:18 -0500 Subject: [PATCH 021/101] Fixed bug. --- toxcore/tox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 3f344ffe..6b16a8d4 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -603,7 +603,7 @@ bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data) { Messenger *m = tox; - m_callback_friendmessage(m, function, user_data); + m_callback_namechange(m, function, user_data); } size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) From ca997bda701f27454b4f5cd54a94f4166ab8e235 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 25 Feb 2015 20:51:37 -0500 Subject: [PATCH 022/101] toxav new api fixes. --- toxav/toxav.c | 2 +- toxav/toxav.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/toxav/toxav.c b/toxav/toxav.c index f8605fd5..e6d41d3a 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -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 */ diff --git a/toxav/toxav.h b/toxav/toxav.h index 3696f961..7285f45c 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -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 From 76dfccf2d6386c1dd1a7e62586ceb1e18618b328 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 25 Feb 2015 21:09:14 -0500 Subject: [PATCH 023/101] Ported some tests to the new api. --- auto_tests/messenger_test.c | 14 ++++---- auto_tests/tox_test.c | 65 ++++++++++++++++++++--------------- auto_tests/toxav_basic_test.c | 47 ++++++++++++------------- auto_tests/toxav_many_test.c | 52 ++++++++++++++-------------- toxcore/Messenger.c | 10 ------ 5 files changed, 94 insertions(+), 94 deletions(-) diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index f1a1ab9b..8c71d6e7 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -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_sendmessage(m, -1, (uint8_t *)message, good_len, 0) == -1); + ck_assert(m_sendmessage(m, REALLY_BIG_NUMBER, (uint8_t *)message, good_len, 0) == -1); + ck_assert(m_sendmessage(m, 17, (uint8_t *)message, good_len, 0) == -1); + ck_assert(m_sendmessage(m, friend_id_num, (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 diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 2c157b1c..7e375db0 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -21,18 +21,18 @@ #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, const uint8_t *string, size_t length, void *userdata) { if (*((uint32_t *)userdata) != 974536) return; @@ -46,7 +46,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; @@ -57,7 +57,7 @@ void print_nickchange(Tox *m, int friendnumber, const uint8_t *string, uint16_t 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; @@ -144,27 +144,35 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *dat 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."); + 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_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."); + 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 +181,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_save_size(tox1); uint8_t data[save_size]; tox_save(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); diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index 3139c844..59730edf 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -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_iteration(bootstrap_node); tox_iteration(Alice); tox_iteration(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,34 @@ 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_iteration(bootstrap_node); + tox_iteration(Alice); + tox_iteration(Bob); - if (tox_isconnected(bootstrap_node) && tox_isconnected(Alice) && tox_isconnected(Bob) && off) { + if (tox_get_connection_status(bootstrap_node) && tox_get_connection_status(Alice) && tox_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 +484,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_do(bootstrap_node); - tox_do(Alice); - tox_do(Bob); + tox_iteration(bootstrap_node); + tox_iteration(Alice); + tox_iteration(Bob); switch ( step ) { case 0: /* Alice */ @@ -524,9 +525,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_do(bootstrap_node); - tox_do(Alice); - tox_do(Bob); + tox_iteration(bootstrap_node); + tox_iteration(Alice); + tox_iteration(Bob); toxav_do(status_control.Alice.av); toxav_do(status_control.Bob.av); @@ -569,9 +570,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_do(bootstrap_node); - tox_do(Alice); - tox_do(Bob); + tox_iteration(bootstrap_node); + tox_iteration(Alice); + tox_iteration(Bob); toxav_do(status_control.Alice.av); toxav_do(status_control.Bob.av); diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index 99012992..4002c4e7 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -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_iteration(bootstrap_node); + tox_iteration(caller); for (i = 0; i < 3; i ++) { - tox_do(callees[i]); + tox_iteration(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_get_connection_status(bootstrap_node) && + tox_get_connection_status(caller) && + tox_get_connection_status(callees[0]) && + tox_get_connection_status(callees[1]) && + tox_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_iteration(bootstrap_node); + tox_iteration(caller); + tox_iteration(callees[0]); + tox_iteration(callees[1]); + tox_iteration(callees[2]); for ( i = 0; i < 3; i++ ) toxav_do(status_control.calls[0].Caller.av); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 863259ac..22adb088 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -491,21 +491,11 @@ static int send_message_generic(Messenger *m, int32_t friendnumber, const uint8_ return 0; } -/* Send a text chat message to an online friend. - * - * return the message id if packet was successfully put into the send queue. - * return 0 if it was not. - */ int m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, uint32_t *message_id) { return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE, 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. - */ int m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length, uint32_t *message_id) { return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION, message_id); From 33370edee66b27c4bd2b6b838c764241d737769e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 26 Feb 2015 08:05:57 -0500 Subject: [PATCH 024/101] Changes to custom packet functions in Messenger. Added function for rtp A/V packets, modified functions to behave correctly for the new api. --- toxav/rtp.c | 6 ++--- toxcore/Messenger.c | 61 +++++++++++++++++++++++---------------------- toxcore/Messenger.h | 41 +++++++++++++++--------------- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/toxav/rtp.c b/toxav/rtp.c index 63c2cdcb..beef1919 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -341,7 +341,7 @@ RTPMessage *msg_parse ( const uint8_t *data, int length ) /** * Callback for networking core. */ -int rtp_handle_packet ( Messenger *m, uint32_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; @@ -469,7 +469,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 +514,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 ); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 22adb088..33d087de 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1333,17 +1333,30 @@ static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_ if (friend_not_valid(m, friend_num)) return 1; - if (m->friendlist[friend_num].lossy_packethandlers[packet[0] % PACKET_ID_LOSSY_RANGE_SIZE].function) - return m->friendlist[friend_num].lossy_packethandlers[packet[0] % PACKET_ID_LOSSY_RANGE_SIZE].function( - m, friend_num, packet, length, m->friendlist[friend_num].lossy_packethandlers[packet[0] % - PACKET_ID_LOSSY_RANGE_SIZE].object); + if (packet[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) { + if (m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function) + return m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function( + m, friend_num, packet, length, m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % + PACKET_LOSSY_AV_RESERVED].object); + + return 1; + } + + if (m->lossy_packethandler) + m->lossy_packethandler(m, friend_num, packet, length, m->lossy_packethandler_userdata); return 1; } -int custom_lossy_packet_registerhandler(Messenger *m, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object), - void *object) +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) +{ + m->lossy_packethandler = packet_handler_callback; + m->lossy_packethandler_userdata = 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) { if (friend_not_valid(m, friendnumber)) return -1; @@ -1351,14 +1364,16 @@ int custom_lossy_packet_registerhandler(Messenger *m, int32_t friendnumber, uint if (byte < PACKET_ID_LOSSY_RANGE_START) return -1; - if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) + if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) return -1; - m->friendlist[friendnumber].lossy_packethandlers[byte % PACKET_ID_LOSSY_RANGE_SIZE].function = packet_handler_callback; - m->friendlist[friendnumber].lossy_packethandlers[byte % PACKET_ID_LOSSY_RANGE_SIZE].object = object; + m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].function = + packet_handler_callback; + m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].object = object; return 0; } + int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) { if (friend_not_valid(m, friendnumber)) @@ -1384,31 +1399,17 @@ static int handle_custom_lossless_packet(void *object, int friend_num, const uin if (packet[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) return -1; - if (m->friendlist[friend_num].lossless_packethandlers[packet[0] % PACKET_ID_LOSSLESS_RANGE_SIZE].function) - return m->friendlist[friend_num].lossless_packethandlers[packet[0] % PACKET_ID_LOSSLESS_RANGE_SIZE].function( - m, friend_num, packet, length, m->friendlist[friend_num].lossless_packethandlers[packet[0] % - PACKET_ID_LOSSLESS_RANGE_SIZE].object); + if (m->lossless_packethandler) + m->lossless_packethandler(m, friend_num, packet, length, m->lossless_packethandler_userdata); return 1; } -int custom_lossless_packet_registerhandler(Messenger *m, int32_t friendnumber, uint8_t byte, - int (*packet_handler_callback)(Messenger *m, uint32_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) { - if (friend_not_valid(m, friendnumber)) - return -1; - - if (byte < PACKET_ID_LOSSLESS_RANGE_START) - return -1; - - if (byte >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) - return -1; - - m->friendlist[friendnumber].lossless_packethandlers[byte % PACKET_ID_LOSSLESS_RANGE_SIZE].function = - packet_handler_callback; - m->friendlist[friendnumber].lossless_packethandlers[byte % PACKET_ID_LOSSLESS_RANGE_SIZE].object = object; - return 0; + m->lossless_packethandler = packet_handler_callback; + m->lossless_packethandler_userdata = object; } int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 48235900..5d5e5879 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -63,6 +63,7 @@ /* 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; @@ -179,14 +180,9 @@ typedef struct { struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; struct { - int (*function)(Messenger *m, uint32_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]; - - struct { - int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object); - void *object; - } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; + } lossy_rtp_packethandlers[PACKET_LOSSY_AV_RESERVED]; struct Receipts *receipts_start; struct Receipts *receipts_end; @@ -260,6 +256,11 @@ struct Messenger { 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; + Messenger_Options options; }; @@ -631,16 +632,21 @@ void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_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, uint32_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. * @@ -652,14 +658,9 @@ 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, uint32_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. * From e61e2919a92ca76e554c9fdc135d0a6ea5d6aedb Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 26 Feb 2015 08:24:19 -0500 Subject: [PATCH 025/101] More tests ported to new api. --- auto_tests/tox_test.c | 148 ++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 70 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 7e375db0..d9cb46db 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -70,12 +70,12 @@ void print_typingchange(Tox *m, uint32_t friendnumber, bool typing, void *userda 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); @@ -86,7 +86,7 @@ int handle_custom_packet(Tox *m, int32_t friend_num, const uint8_t *data, uint32 printf("Custom packet fail. %u\n", number ); } - return 0; + return; } uint8_t filenum; @@ -208,32 +208,33 @@ 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 *tox1 = tox_new(0, 0, 0, 0); + Tox *tox2 = tox_new(0, 0, 0, 0); + Tox *tox3 = tox_new(0, 0, 0, 0); ck_assert_msg(tox1 || tox2 || tox3, "Failed to create 3 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(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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); - if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { + if (tox_get_connection_status(tox1) && tox_get_connection_status(tox2) && tox_get_connection_status(tox3) && 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); @@ -244,15 +245,17 @@ START_TEST(test_few_clients) 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_SEND_MESSAGE errm; + tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm); + ck_assert_msg(errm == TOX_ERR_SEND_MESSAGE_TOO_LONG, "TOX_MAX_MESSAGE_LENGTH is too small\n"); + tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); + ck_assert_msg(errm == TOX_ERR_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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (messages_received) break; @@ -262,14 +265,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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (name_changes) break; @@ -277,18 +282,19 @@ 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_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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (typing_changes == 2) @@ -299,14 +305,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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (typing_changes == 1) break; @@ -316,23 +322,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_send_lossless_packet(tox2, 0, data_c, sizeof(data_c), 0); + ck_assert_msg(ret == 0, "tox_send_lossless_packet bigger fail %i", ret); + ret = tox_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0); + ck_assert_msg(ret == 1, "tox_send_lossless_packet fail %i", ret); while (1) { custom_packet = 0; - tox_do(tox1); - tox_do(tox2); - tox_do(tox3); + tox_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (custom_packet == 1) break; @@ -343,19 +350,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_send_lossy_packet(tox2, 0, data_c, sizeof(data_c), 0); + ck_assert_msg(ret == 0, "tox_send_lossy_packet bigger fail %i", ret); + ret = tox_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0); + ck_assert_msg(ret == 1, "tox_send_lossy_packet fail %i", ret); while (1) { custom_packet = 0; - tox_do(tox1); - tox_do(tox2); - tox_do(tox3); + tox_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (custom_packet == 1) break; @@ -381,9 +387,9 @@ START_TEST(test_few_clients) while (1) { file_sent = 0; - tox_do(tox1); - tox_do(tox2); - tox_do(tox3); + tox_iteration(tox1); + tox_iteration(tox2); + tox_iteration(tox3); if (sendf_ok) while (tox_file_send_data(tox2, 0, fnum, f_data, fpiece_size < totalf_size ? fpiece_size : totalf_size) == 0) { @@ -401,9 +407,9 @@ START_TEST(test_few_clients) if (file_sent && size_recv == file_size) break; - 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); @@ -433,7 +439,7 @@ 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); } @@ -443,7 +449,7 @@ START_TEST(test_many_clients) 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: @@ -455,22 +461,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_friend_list_size(toxes[i]); ++j) + if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_UDP) ++counter; } @@ -479,7 +487,7 @@ loop_top: } for (i = 0; i < NUM_TOXES; ++i) { - tox_do(toxes[i]); + tox_iteration(toxes[i]); } c_sleep(50); From e5791ed9ef59ee5786016b39686b3d9aacf940c0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 26 Feb 2015 13:13:26 -0500 Subject: [PATCH 026/101] Added different error codes for custom packet functions in Messenger. --- toxav/rtp.c | 7 ++++--- toxcore/Messenger.c | 33 +++++++++++++++++++++++---------- toxcore/Messenger.h | 12 ++++++++++-- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/toxav/rtp.c b/toxav/rtp.c index beef1919..ccac7564 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -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 ); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 33d087de..aa7b05bc 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1379,11 +1379,24 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin if (friend_not_valid(m, friendnumber)) return -1; - if (m->friendlist[friendnumber].status != FRIEND_ONLINE) - return -1; + if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) + return -2; - return send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, - m->friendlist[friendnumber].friendcon_id), data, length); + if (data[0] < PACKET_ID_LOSSY_RANGE_START) + return -3; + + if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) + return -3; + + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -4; + + if (send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), data, length) == -1) { + return -5; + } else { + return 0; + } } static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) @@ -1417,21 +1430,21 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const if (friend_not_valid(m, friendnumber)) return -1; - if (length == 0) - return -1; + if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) + return -2; if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) - return -1; + return -3; if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) - return -1; + return -3; if (m->friendlist[friendnumber].status != FRIEND_ONLINE) - return -1; + return -4; if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) { - return -1; + return -5; } else { return 0; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 5d5e5879..f4046f2e 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -650,7 +650,11 @@ void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_cal /* 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); @@ -664,7 +668,11 @@ void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_ /* 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); From c5b03cdd9a5c24d31870dfd474507a097f93b60b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 26 Feb 2015 13:17:22 -0500 Subject: [PATCH 027/101] Implemented custom packet functions in new api. --- toxcore/tox.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/toxcore/tox.c b/toxcore/tox.c index 6b16a8d4..e95bbefb 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -809,3 +809,100 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * m_callback_action(m, function, user_data); } +static void set_custom_packet_error(int ret, TOX_ERR_SEND_CUSTOM_PACKET *error) +{ + switch (ret) { + case 0: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_OK); + break; + + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_FOUND); + break; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_TOO_LONG); + break; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_INVALID); + break; + + case -4: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED); + break; + + case -5: + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_SENDQ); + break; + } +} + +bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_SEND_CUSTOM_PACKET *error) +{ + if (!data) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_NULL); + return 0; + } + + Messenger *m = tox; + + if (length == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_EMPTY); + return 0; + } + + if (data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_INVALID); + return 0; + } + + int ret = send_custom_lossy_packet(m, friend_number, data, length); + + set_custom_packet_error(ret, error); + + if (ret == 0) { + return 1; + } else { + return 0; + } +} + +void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *function, void *user_data) +{ + Messenger *m = tox; + custom_lossy_packet_registerhandler(m, function, user_data); +} + +bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_SEND_CUSTOM_PACKET *error) +{ + if (!data) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_NULL); + return 0; + } + + Messenger *m = tox; + + if (length == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_EMPTY); + return 0; + } + + int ret = send_custom_lossless_packet(m, friend_number, data, length); + + set_custom_packet_error(ret, error); + + if (ret == 0) { + return 1; + } else { + return 0; + } +} + +void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *function, void *user_data) +{ + Messenger *m = tox; + custom_lossless_packet_registerhandler(m, function, user_data); +} From 6e8762b30a17b515deb74c62a3a98db4206d363e Mon Sep 17 00:00:00 2001 From: saneki Date: Fri, 27 Feb 2015 11:58:00 -0600 Subject: [PATCH 028/101] Allow for specifying the port range to use in Tox_Options --- toxcore/Messenger.c | 2 +- toxcore/Messenger.h | 1 + toxcore/network.c | 38 +++++++++++++++++++++++++++++++++----- toxcore/network.h | 1 + toxcore/tox.c | 2 ++ toxcore/tox.h | 19 +++++++++++++++++++ 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index aa7b05bc..544b8b0d 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1484,7 +1484,7 @@ Messenger *new_messenger(Messenger_Options *options) } else { IP ip; ip_init(&ip, options->ipv6enabled); - m->net = new_networking(ip, TOX_PORT_DEFAULT); + m->net = new_networking_ex(ip, options->port_range[0], options->port_range[1]); } if (m->net == NULL) { diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index f4046f2e..4659ddf9 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -69,6 +69,7 @@ typedef struct { uint8_t ipv6enabled; uint8_t udp_disabled; TCP_Proxy_Info proxy_info; + uint16_t port_range[2]; } Messenger_Options; diff --git a/toxcore/network.c b/toxcore/network.c index deccbb63..9433e368 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -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)); +} + /* Initialize networking. * Bind to ip and port. * ip must be in network order EX: 127.0.0.1 = (7F000001). @@ -474,8 +482,28 @@ static void at_shutdown(void) * return Networking_Core object if no problems * return NULL if there are problems. */ -Networking_Core *new_networking(IP ip, uint16_t port) +Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) { + /* 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; + } + /* 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 +628,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) { @@ -623,8 +651,8 @@ Networking_Core *new_networking(IP ip, uint16_t port) 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); } diff --git a/toxcore/network.h b/toxcore/network.h index 15e1c0a4..0e7e5948 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -364,6 +364,7 @@ void networking_poll(Networking_Core *net); * return NULL if there are problems. */ Networking_Core *new_networking(IP ip, uint16_t port); +Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to); /* Function to cleanup networking stuff (doesn't do much right now). */ void kill_networking(Networking_Core *net); diff --git a/toxcore/tox.c b/toxcore/tox.c index e95bbefb..fc6ffc2b 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -107,6 +107,8 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng } else { m_options.ipv6enabled = options->ipv6_enabled; m_options.udp_disabled = !options->udp_enabled; + m_options.port_range[0] = options->start_port; + m_options.port_range[1] = options->end_port; switch (options->proxy_type) { case TOX_PROXY_TYPE_HTTP: diff --git a/toxcore/tox.h b/toxcore/tox.h index 2acc70ea..a66bcb17 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -353,6 +353,25 @@ struct Tox_Options { * proxy_enabled is false. */ uint16_t proxy_port; + + /** + * The start port of the inclusive port range to attempt to use. + * + * If both start_port and end_port are 0, the default port range will be + * used: [33445, 33545]. + * + * If either start_port or end_port is 0 while the other is non-zero, the + * non-zero port will be the only port in the range. + * + * Having start_port > end_port will yield the same behavior as if start_port + * and end_port were swapped. + */ + uint16_t start_port; + + /** + * The end port of the inclusive port range to attempt to use. + */ + uint16_t end_port; }; From e632ef8a478ebb964b855c641e2ba14b279c78e1 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 27 Feb 2015 17:42:36 -0600 Subject: [PATCH 029/101] Realign toxencryptsave with new API --- toxcore/tox.h | 8 ++++++++ toxencryptsave/toxencryptsave.c | 36 ++++++++++++++++----------------- toxencryptsave/toxencryptsave.h | 25 +++++++++++++++-------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index 2acc70ea..abae26e6 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -443,6 +443,14 @@ enum TOX_ERR_NEW { * The byte array to be loaded contained an encrypted save. */ TOX_ERR_NEW_LOAD_ENCRYPTED, + /** + * The encrypted byte array could not be decrypted. Either the data was + * corrupt or the password/key was incorrect. + * + * NOTE: This error code is only set by tox_encrypted_new() and + * tox_encrypted_key_new(), in the toxencryptsave module. + */ + TOX_ERR_NEW_LOAD_DECRYPTION_FAILED, /** * The data format was invalid. This can happen when loading data that was * saved by an older version of Tox, or when the data has been corrupted. diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 13a34dea..b801e1ba 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -29,6 +29,7 @@ #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" @@ -293,38 +294,42 @@ 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) @@ -339,8 +344,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); -} diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index da13f312..ea5f4eab 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -29,10 +29,13 @@ extern "C" { #endif #include +#include #ifndef TOX_DEFINED #define TOX_DEFINED typedef struct Tox Tox; +struct Tox_Options; +typedef uint8_t 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,12 @@ 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 +167,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 +184,12 @@ 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 +197,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 } From d015879cd3d24ddc8f81964b64d0ce199cd75913 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 27 Feb 2015 20:33:43 -0500 Subject: [PATCH 030/101] Test fixes. --- auto_tests/tox_test.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index d9cb46db..d7a44fb2 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -503,13 +503,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); } } @@ -560,24 +560,24 @@ 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); + 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; } } @@ -586,7 +586,7 @@ START_TEST(test_many_group) break; for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_do(toxes[i]); + tox_iteration(toxes[i]); } c_sleep(50); @@ -604,7 +604,7 @@ START_TEST(test_many_group) while (1) { for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_do(toxes[i]); + tox_iteration(toxes[i]); } if (!invite_counter) { @@ -642,7 +642,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_iteration(toxes[i]); } c_sleep(50); @@ -655,7 +655,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_iteration(toxes[i]); } c_sleep(50); From 8e59a826cb326e1c2cfefb775d9e0762c6ffe79b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 27 Feb 2015 21:18:43 -0500 Subject: [PATCH 031/101] Removed backwards compatibility code from core. That function should be static. --- toxcore/Messenger.c | 7 +------ toxcore/Messenger.h | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index aa7b05bc..17cfd182 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1002,7 +1002,7 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u * return 1 on success * return 0 on failure */ -int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, +static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length) { if (friend_not_valid(m, friendnumber)) @@ -1612,11 +1612,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) if (packet_id == PACKET_ID_ONLINE && len == 1) { set_friend_status(m, i, FRIEND_ONLINE); send_online_packet(m, i); - } else if (packet_id == PACKET_ID_NICKNAME || packet_id == PACKET_ID_STATUSMESSAGE - || packet_id == PACKET_ID_USERSTATUS) { - /* Some backward compatibility, TODO: remove. */ - set_friend_status(m, i, FRIEND_ONLINE); - send_online_packet(m, i); } else { return -1; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index f4046f2e..4aeb780e 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -575,14 +575,6 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u uint16_t length, void *), void *userdata); -/* Send a file send request. - * Maximum filename length is 255 bytes. - * return 1 on success - * return 0 on failure - */ -int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length); - /* Send a file send request. * Maximum filename length is 255 bytes. * return file number on success From 2d3077904ec9360eb1f753643a16a15f0fb739c5 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sat, 28 Feb 2015 12:55:40 -0600 Subject: [PATCH 032/101] Update encryption autotest --- auto_tests/encryptsave_test.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 338c9ef1..9ff63a7d 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -55,6 +55,7 @@ END_TEST START_TEST(test_save_friend) { + TOX_ERR_NEW err = TOX_ERR_NEW_OK; Tox *tox1 = tox_new(0); Tox *tox2 = tox_new(0); ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances"); @@ -71,9 +72,8 @@ START_TEST(test_save_friend) ck_assert_msg(test == 0, "failed to encrypted save"); 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"); + 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_CLIENT_ID_SIZE]; test = tox_get_client_id(tox3, 0, address2); ck_assert_msg(test == 0, "no friends!"); @@ -88,18 +88,17 @@ START_TEST(test_save_friend) 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"); - // 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"); + // 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_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"); - // 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,9 +106,8 @@ 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"); + 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_CLIENT_ID_SIZE]; test = tox_get_client_id(tox4, 0, address5); ck_assert_msg(test == 0, "no friends! the third"); From 36c3a270fd5fff5e33371a91861db16e5816964a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 1 Mar 2015 20:31:55 -0500 Subject: [PATCH 033/101] Properly fixed encryptsave_test.c --- auto_tests/encryptsave_test.c | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 9ff63a7d..de78a0c2 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -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); } } @@ -56,28 +56,28 @@ END_TEST START_TEST(test_save_friend) { TOX_ERR_NEW err = TOX_ERR_NEW_OK; - 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); 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_encrypted_new(0, data, size, "correcthorsebatterystaple", 25, &err); ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new"); - 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!"); + 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,15 +86,15 @@ 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_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_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"); + 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_new, first manually... uint8_t out1[size], out2[size]; @@ -108,10 +108,10 @@ START_TEST(test_save_friend) // to remove the manual check now that it's there) 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_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"); + 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); From 85249111775bdcbeb946d60e59bd21b0d33e8e6d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 4 Mar 2015 20:28:17 -0500 Subject: [PATCH 034/101] Removed useless TODO comments. --- toxcore/Messenger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f6c37ac4..8bddd6bc 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -133,8 +133,7 @@ int getfriendcon_id(const Messenger *m, int32_t friendnumber) return m->friendlist[friendnumber].friendcon_id; } -/* TODO: Another checksum algorithm might be better. - * +/* * return a uint16_t that represents the checksum of address of length len. */ static uint16_t address_checksum(const uint8_t *address, uint32_t len) @@ -1836,7 +1835,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) return 0; } -/* TODO: Make this function not suck. */ void do_friends(Messenger *m) { uint32_t i; From ac7da66529884da7db6a72fdf20f02748b849396 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 5 Mar 2015 12:30:50 -0500 Subject: [PATCH 035/101] Code cleanups. Fixed wrong variable used, removed useless elements of struct. --- toxcore/Messenger.c | 4 ++-- toxcore/Messenger.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 8bddd6bc..94cb93dd 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -826,7 +826,7 @@ void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint3 void *userdata) { m->friend_statusmessagechange = function; - m->friend_statuschange_userdata = userdata; + m->friend_statusmessagechange_userdata = userdata; } void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), void *userdata) @@ -1654,7 +1654,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) if (m->friend_statusmessagechange) m->friend_statusmessagechange(m, i, data_terminated, data_length, - m->friend_statuschange_userdata); + m->friend_statusmessagechange_userdata); set_friend_statusmessage(m, i, data_terminated, data_length); break; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 541894ab..67c2358d 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -236,8 +236,6 @@ struct Messenger { void *friend_typingchange_userdata; void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *); void *read_receipt_userdata; - void (*friend_statuschange)(struct Messenger *m, uint32_t, uint8_t, void *); - void *friend_statuschange_userdata; void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, uint8_t, void *); void *friend_connectionstatuschange_userdata; void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *); From f66f9fe76ee491dfb0882860d0bcfd6acbbfe95f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 5 Mar 2015 12:49:38 -0500 Subject: [PATCH 036/101] enums are no longer typedefed to uint8_t. --- toxcore/Messenger.c | 4 +- toxcore/Messenger.h | 9 ++-- toxcore/tox.h | 114 ++++++++++++++++++++------------------------ 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 94cb93dd..373fc334 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -829,7 +829,7 @@ void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint3 m->friend_statusmessagechange_userdata = userdata; } -void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), void *userdata) +void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), void *userdata) { m->friend_userstatuschange = function; m->friend_userstatuschange_userdata = userdata; @@ -847,7 +847,7 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32 m->read_receipt_userdata = userdata; } -void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), +void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), void *userdata) { m->friend_connectionstatuschange = function; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 67c2358d..90c66e2c 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -230,13 +230,13 @@ struct Messenger { void *friend_namechange_userdata; void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); void *friend_statusmessagechange_userdata; - void (*friend_userstatuschange)(struct Messenger *m, uint32_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, uint32_t, _Bool, void *); void *friend_typingchange_userdata; void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *); void *read_receipt_userdata; - void (*friend_connectionstatuschange)(struct Messenger *m, uint32_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, uint32_t, uint8_t, void *); void *friend_connectionstatuschange_internal_userdata; @@ -495,7 +495,8 @@ void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint3 /* Set the callback for status type changes. * Function(uint32_t friendnumber, USERSTATUS kind) */ -void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_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(uint32_t friendnumber, uint8_t is_typing) @@ -524,7 +525,7 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32 * 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, uint32_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, uint32_t, uint8_t, void *), diff --git a/toxcore/tox.h b/toxcore/tox.h index 8a489411..23d37cd9 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -260,7 +260,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); /** * Represents the possible statuses a client can have. */ -enum TOX_STATUS { +typedef enum TOX_STATUS { /** * User is online and available. */ @@ -279,8 +279,8 @@ enum TOX_STATUS { * Invalid status used when function returns an error. */ TOX_STATUS_INVALID -}; -typedef uint8_t TOX_STATUS; +} TOX_STATUS; + /******************************************************************************* * @@ -289,7 +289,7 @@ typedef uint8_t TOX_STATUS; ******************************************************************************/ -enum TOX_PROXY_TYPE { +typedef enum TOX_PROXY_TYPE { /** * Don't use a proxy. */ @@ -302,8 +302,8 @@ enum TOX_PROXY_TYPE { * SOCKS proxy for simple socket pipes. */ TOX_PROXY_TYPE_SOCKS5 -}; -typedef uint8_t TOX_PROXY_TYPE; +} TOX_PROXY_TYPE; + /** * This struct contains all the startup options for Tox. You can either allocate @@ -389,14 +389,13 @@ struct Tox_Options { void tox_options_default(struct Tox_Options *options); -enum TOX_ERR_OPTIONS_NEW { +typedef enum TOX_ERR_OPTIONS_NEW { TOX_ERR_OPTIONS_NEW_OK, /** * The function failed to allocate enough memory for the options struct. */ TOX_ERR_OPTIONS_NEW_MALLOC -}; -typedef uint8_t TOX_ERR_OPTIONS_NEW; +} TOX_ERR_OPTIONS_NEW; /** * Allocates a new Tox_Options object and initialises it with the default @@ -427,7 +426,7 @@ void tox_options_free(struct Tox_Options *options); ******************************************************************************/ -enum TOX_ERR_NEW { +typedef enum TOX_ERR_NEW { TOX_ERR_NEW_OK, TOX_ERR_NEW_NULL, /** @@ -478,8 +477,8 @@ enum TOX_ERR_NEW { * causes this error. */ TOX_ERR_NEW_LOAD_BAD_FORMAT -}; -typedef uint8_t TOX_ERR_NEW; +} TOX_ERR_NEW; + /** * @brief Creates and initialises a new Tox instance with the options passed. @@ -539,7 +538,7 @@ void tox_save(const Tox *tox, uint8_t *data); ******************************************************************************/ -enum TOX_ERR_BOOTSTRAP { +typedef enum TOX_ERR_BOOTSTRAP { TOX_ERR_BOOTSTRAP_OK, TOX_ERR_BOOTSTRAP_NULL, /** @@ -551,8 +550,7 @@ enum TOX_ERR_BOOTSTRAP { * The port passed was invalid. The valid port range is (1, 65535). */ TOX_ERR_BOOTSTRAP_BAD_PORT -}; -typedef uint8_t TOX_ERR_BOOTSTRAP; +} TOX_ERR_BOOTSTRAP; /** * Sends a "get nodes" request to the given bootstrap node with IP, port, and @@ -593,7 +591,7 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8 TOX_ERR_BOOTSTRAP *error); -enum TOX_CONNECTION { +typedef enum TOX_CONNECTION { /** * There is no connection. This instance, or the friend the state change is * about, is now offline. @@ -612,8 +610,8 @@ enum TOX_CONNECTION { * particular friend was built using direct UDP packets. */ TOX_CONNECTION_UDP -}; -typedef uint8_t TOX_CONNECTION; +} TOX_CONNECTION; + /** * Return whether we are connected to the DHT. The return value is equal to the @@ -716,15 +714,15 @@ void tox_self_get_private_key(const Tox *tox, uint8_t *private_key); * Common error codes for all functions that set a piece of user-visible * client information. */ -enum TOX_ERR_SET_INFO { +typedef enum TOX_ERR_SET_INFO { TOX_ERR_SET_INFO_OK, TOX_ERR_SET_INFO_NULL, /** * Information length exceeded maximum permissible size. */ TOX_ERR_SET_INFO_TOO_LONG -}; -typedef uint8_t TOX_ERR_SET_INFO; +} TOX_ERR_SET_INFO; + /** * Set the nickname for the Tox client. @@ -818,7 +816,7 @@ TOX_STATUS tox_self_get_status(const Tox *tox); ******************************************************************************/ -enum TOX_ERR_FRIEND_ADD { +typedef enum TOX_ERR_FRIEND_ADD { TOX_ERR_FRIEND_ADD_OK, TOX_ERR_FRIEND_ADD_NULL, /** @@ -852,8 +850,7 @@ enum TOX_ERR_FRIEND_ADD { * A memory allocation failed when trying to increase the friend list size. */ TOX_ERR_FRIEND_ADD_MALLOC -}; -typedef uint8_t TOX_ERR_FRIEND_ADD; +} TOX_ERR_FRIEND_ADD; /** * Add a friend to the friend list and send a friend request. @@ -902,14 +899,13 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error); -enum TOX_ERR_FRIEND_DELETE { +typedef enum TOX_ERR_FRIEND_DELETE { TOX_ERR_FRIEND_DELETE_OK, /** * There was no friend with the given friend number. No friends were deleted. */ TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND -}; -typedef uint8_t TOX_ERR_FRIEND_DELETE; +} TOX_ERR_FRIEND_DELETE; /** * Remove a friend from the friend list. @@ -932,15 +928,14 @@ bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE * ******************************************************************************/ -enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { +typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL, /** * No friend with the given Public Key exists on the friend list. */ TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND -}; -typedef uint8_t TOX_ERR_FRIEND_BY_PUBLIC_KEY; +} TOX_ERR_FRIEND_BY_PUBLIC_KEY; /** * Return the friend number associated with that Public Key. @@ -951,15 +946,14 @@ typedef uint8_t TOX_ERR_FRIEND_BY_PUBLIC_KEY; uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); -enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { +typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL, /** * No friend with the given number exists on the friend list. */ TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND -}; -typedef uint8_t TOX_ERR_FRIEND_GET_PUBLIC_KEY; +} TOX_ERR_FRIEND_GET_PUBLIC_KEY; /** * Copies the Public Key associated with a given friend number to a byte array. @@ -1012,7 +1006,7 @@ void tox_friend_list(const Tox *tox, uint32_t *list); /** * Common error codes for friend state query functions. */ -enum TOX_ERR_FRIEND_QUERY { +typedef enum TOX_ERR_FRIEND_QUERY { TOX_ERR_FRIEND_QUERY_OK, /** * The pointer parameter for storing the query result (name, message) was @@ -1024,8 +1018,8 @@ enum TOX_ERR_FRIEND_QUERY { * The friend_number did not designate a valid friend. */ TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND -}; -typedef uint8_t TOX_ERR_FRIEND_QUERY; +} TOX_ERR_FRIEND_QUERY; + /** * Return the length of the friend's name. If the friend number is invalid, the @@ -1213,14 +1207,13 @@ void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void * ******************************************************************************/ -enum TOX_ERR_SET_TYPING { +typedef enum TOX_ERR_SET_TYPING { TOX_ERR_SET_TYPING_OK, /** * The friend number did not designate a valid friend. */ TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND -}; -typedef uint8_t TOX_ERR_SET_TYPING; +} TOX_ERR_SET_TYPING; /** * Set the client's typing status for a friend. @@ -1235,7 +1228,7 @@ typedef uint8_t TOX_ERR_SET_TYPING; bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error); -enum TOX_ERR_SEND_MESSAGE { +typedef enum TOX_ERR_SEND_MESSAGE { TOX_ERR_SEND_MESSAGE_OK, TOX_ERR_SEND_MESSAGE_NULL, /** @@ -1258,8 +1251,7 @@ enum TOX_ERR_SEND_MESSAGE { * Attempted to send a zero-length message. */ TOX_ERR_SEND_MESSAGE_EMPTY -}; -typedef uint8_t TOX_ERR_SEND_MESSAGE; +} TOX_ERR_SEND_MESSAGE; /** * Send a text chat message to an online friend. @@ -1398,7 +1390,7 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * ******************************************************************************/ -enum TOX_FILE_KIND { +typedef enum TOX_FILE_KIND { /** * Arbitrary file data. Clients can choose to handle it based on the file name * or magic or any other way they choose. @@ -1421,8 +1413,8 @@ enum TOX_FILE_KIND { * transfer if it matches. */ TOX_FILE_KIND_AVATAR -}; -typedef uint8_t TOX_FILE_KIND; +} TOX_FILE_KIND; + /** * Generates a cryptographic hash of the given data. @@ -1446,7 +1438,7 @@ typedef uint8_t TOX_FILE_KIND; bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length); -enum TOX_FILE_CONTROL { +typedef enum TOX_FILE_CONTROL { /** * Sent by the receiving side to accept a file send request. Also sent after a * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving. @@ -1464,10 +1456,10 @@ enum TOX_FILE_CONTROL { * commands are sent. Also sent by either side to terminate a file transfer. */ TOX_FILE_CONTROL_CANCEL -}; -typedef uint8_t TOX_FILE_CONTROL; +} TOX_FILE_CONTROL; -enum TOX_ERR_FILE_CONTROL { + +typedef enum TOX_ERR_FILE_CONTROL { TOX_ERR_FILE_CONTROL_OK, /** * The friend_number passed did not designate a valid friend. @@ -1494,8 +1486,7 @@ enum TOX_ERR_FILE_CONTROL { * A PAUSE control was sent, but the file transfer was already paused. */ TOX_ERR_FILE_CONTROL_ALREADY_PAUSED -}; -typedef uint8_t TOX_ERR_FILE_CONTROL; +} TOX_ERR_FILE_CONTROL; /** * Sends a file control command to a friend for a given file transfer. @@ -1541,7 +1532,7 @@ void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *us ******************************************************************************/ -enum TOX_ERR_FILE_SEND { +typedef enum TOX_ERR_FILE_SEND { TOX_ERR_FILE_SEND_OK, TOX_ERR_FILE_SEND_NULL, /** @@ -1565,8 +1556,7 @@ enum TOX_ERR_FILE_SEND { * is 256 per friend per direction (sending and receiving). */ TOX_ERR_FILE_SEND_TOO_MANY -}; -typedef uint8_t TOX_ERR_FILE_SEND; +} TOX_ERR_FILE_SEND; /** * Send a file transmission request. @@ -1627,7 +1617,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uin const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); -enum TOX_ERR_FILE_SEND_CHUNK { +typedef enum TOX_ERR_FILE_SEND_CHUNK { TOX_ERR_FILE_SEND_CHUNK_OK, /** * The length parameter was non-zero, but data was NULL. @@ -1651,8 +1641,7 @@ enum TOX_ERR_FILE_SEND_CHUNK { * the file. Trying to send more will result in no data being sent. */ TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE -}; -typedef uint8_t TOX_ERR_FILE_SEND_CHUNK; +} TOX_ERR_FILE_SEND_CHUNK; /** * Send a chunk of file data to a friend. @@ -1790,7 +1779,7 @@ void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *functi ******************************************************************************/ -enum TOX_ERR_SEND_CUSTOM_PACKET { +typedef enum TOX_ERR_SEND_CUSTOM_PACKET { TOX_ERR_SEND_CUSTOM_PACKET_OK, TOX_ERR_SEND_CUSTOM_PACKET_NULL, /** @@ -1818,8 +1807,8 @@ enum TOX_ERR_SEND_CUSTOM_PACKET { * Send queue size exceeded. */ TOX_ERR_SEND_CUSTOM_PACKET_SENDQ -}; -typedef uint8_t TOX_ERR_SEND_CUSTOM_PACKET; +} TOX_ERR_SEND_CUSTOM_PACKET; + /** * Send a custom lossy packet to a friend. @@ -1918,14 +1907,13 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb void tox_get_dht_id(const Tox *tox, uint8_t *dht_id); -enum TOX_ERR_GET_PORT { +typedef enum TOX_ERR_GET_PORT { TOX_ERR_GET_PORT_OK, /** * The instance was not bound to any port. */ TOX_ERR_GET_PORT_NOT_BOUND -}; -typedef uint8_t TOX_ERR_GET_PORT; +} TOX_ERR_GET_PORT; /** * Return the UDP port this Tox instance is bound to. From 20090ea661be7e3cd5eccc47084d220aff0d4607 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 6 Mar 2015 21:37:00 -0500 Subject: [PATCH 037/101] Fixed typedef. --- toxencryptsave/toxencryptsave.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 5ceeefdd..9b613cac 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -35,7 +35,7 @@ extern "C" { #define TOX_DEFINED typedef struct Tox Tox; struct Tox_Options; -typedef uint8_t TOX_ERR_NEW; +typedef enum TOX_ERR_NEW TOX_ERR_NEW; #endif // these functions provide access to these defines in toxencryptsave.c, which From 14af278ca840e29fc1dc559606e3438085948380 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 6 Mar 2015 22:06:58 -0500 Subject: [PATCH 038/101] Updated File request packet to new format. [uint8_t packet_id (PACKET_ID_FILE_SENDREQUEST)][uint8_t file_number] [uint32_t type][uint64_t file_size][filename (currently max 255 bytes)] recv file numbers are << by 16 to distinguish them from sending files. --- toxcore/Messenger.c | 45 +++++++++++++++++++++++++++------------------ toxcore/Messenger.h | 11 ++++++----- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 373fc334..9b5d75fc 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -959,11 +959,10 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin /* Set the callback for file send requests. * - * Function(Tox *tox, uint32_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, unsigned int filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata) */ -void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_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, unsigned int, uint64_t, + const uint8_t *, size_t, void *), void *userdata) { m->file_sendrequest = function; m->file_sendrequest_userdata = userdata; @@ -1001,8 +1000,8 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u * return 1 on success * return 0 on failure */ -static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length) +static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, + uint64_t filesize, const uint8_t *filename, uint16_t filename_length) { if (friend_not_valid(m, friendnumber)) return 0; @@ -1010,13 +1009,14 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi if (filename_length > MAX_FILENAME_LENGTH) return 0; - uint8_t packet[MAX_FILENAME_LENGTH + 1 + sizeof(filesize)]; + uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + filename_length]; packet[0] = filenumber; + file_type = htonl(file_type); + memcpy(packet + 1, &file_type, sizeof(file_type)); host_to_net((uint8_t *)&filesize, sizeof(filesize)); - memcpy(packet + 1, &filesize, sizeof(filesize)); - memcpy(packet + 1 + sizeof(filesize), filename, filename_length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, - 1 + sizeof(filesize) + filename_length, 0); + memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize)); + memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), filename, filename_length); + return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, sizeof(packet), 0); } /* Send a file send request. @@ -1040,7 +1040,7 @@ int new_filesender(const Messenger *m, int32_t friendnumber, uint64_t filesize, if (i == MAX_CONCURRENT_FILE_PIPES) return -1; - if (file_sendrequest(m, friendnumber, i, filesize, filename, filename_length) == 0) + if (file_sendrequest(m, friendnumber, i, 0, filesize, filename, filename_length) == 0) return -1; m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NOT_ACCEPTED; @@ -1742,24 +1742,33 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_FILE_SENDREQUEST: { - if (data_length < 1 + sizeof(uint64_t) + 1) + const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t); + + if (data_length < head_length + 1) break; uint8_t filenumber = data[0]; uint64_t filesize; - memcpy(&filesize, data + 1, sizeof(filesize)); + uint32_t file_type; + memcpy(&file_type, data + 1, sizeof(file_type)); + file_type = ntohl(file_type); + + memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); net_to_host((uint8_t *) &filesize, sizeof(filesize)); m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; m->friendlist[i].file_receiving[filenumber].size = filesize; m->friendlist[i].file_receiving[filenumber].transferred = 0; /* Force NULL terminate file name. */ - uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; - memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); - filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; + uint8_t filename_terminated[data_length - head_length + 1]; + memcpy(filename_terminated, data + head_length, data_length - head_length); + filename_terminated[data_length - head_length] = 0; + + uint32_t real_filenumber = filenumber; + real_filenumber <<= 16; if (m->file_sendrequest) - (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), + (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename_terminated, data_length - head_length, m->file_sendrequest_userdata); break; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 90c66e2c..fa0d241c 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -245,7 +245,8 @@ struct Messenger { 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, uint32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *); + void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, unsigned int, uint64_t, const uint8_t *, size_t, + void *); void *file_sendrequest_userdata; void (*file_filecontrol)(struct Messenger *m, uint32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, void *); void *file_filecontrol_userdata; @@ -552,11 +553,11 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin /* Set the callback for file send requests. * - * Function(Tox *tox, uint32_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, unsigned int filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata) */ -void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_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, unsigned int, uint64_t, + const uint8_t *, size_t, void *), void *userdata); + /* Set the callback for file control requests. * From 2af1608059da9dfbf91fd2d25c8367b426ca182a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 7 Mar 2015 16:16:25 -0500 Subject: [PATCH 039/101] Fixed debug fprintf. --- toxcore/network.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 1488d980..4558f6ff 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -655,8 +655,8 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) } #ifdef DEBUG - fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno, - strerror(errno), ip_ntoa(&ip), port); + fprintf(stderr, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u\n", errno, strerror(errno), + ip_ntoa(&ip), port_from, port_to); #endif kill_networking(temp); return NULL; From 10ca292f24725d07fc18c7c07a0afcc79f9a73ec Mon Sep 17 00:00:00 2001 From: Christoffer Sterner Date: Sat, 7 Mar 2015 22:39:27 +0100 Subject: [PATCH 040/101] Change fprintf debug into LOGGER_DEBUG for consistency --- toxcore/network.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 4558f6ff..c184bf07 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -654,10 +654,9 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) *portptr = htons(port_to_try); } -#ifdef DEBUG - fprintf(stderr, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u\n", errno, strerror(errno), + LOGGER_DEBUG("Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), ip_ntoa(&ip), port_from, port_to); -#endif + kill_networking(temp); return NULL; } From 3315fd257146bf423a895cf988b90954294a2efe Mon Sep 17 00:00:00 2001 From: Christoffer Sterner Date: Sat, 7 Mar 2015 23:45:00 +0100 Subject: [PATCH 041/101] Change LOGGER_DEBUG to LOGGER_ERROR for fail bind --- toxcore/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/network.c b/toxcore/network.c index c184bf07..53cadea0 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -654,7 +654,7 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) *portptr = htons(port_to_try); } - LOGGER_DEBUG("Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), + 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); From 4c4ffb74093037ab6cd02d310a07b73022becf83 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 9 Mar 2015 14:32:37 -0400 Subject: [PATCH 042/101] Fixed case where a recv and a sending file would have the same number. recv file numbers are now (file num in packet + 1) << 16 --- toxcore/Messenger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 9b5d75fc..251d00d2 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1765,6 +1765,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) filename_terminated[data_length - head_length] = 0; uint32_t real_filenumber = filenumber; + real_filenumber += 1; real_filenumber <<= 16; if (m->file_sendrequest) From 576e5ee703a3740c558a6e742cc2bcfce5feafbf Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 9 Mar 2015 19:21:51 -0400 Subject: [PATCH 043/101] Updated new_filesender function in Messenger.c --- toxcore/Messenger.c | 20 ++++++++++++++------ toxcore/Messenger.h | 11 ++++++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 251d00d2..ee76b103 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1022,14 +1022,21 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi /* 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 too big. + * 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 *filename, uint16_t filename_length) { if (friend_not_valid(m, friendnumber)) return -1; + if (filename_length > MAX_FILENAME_LENGTH) + return -2; + uint32_t i; for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { @@ -1038,14 +1045,15 @@ int new_filesender(const Messenger *m, int32_t friendnumber, uint64_t filesize, } if (i == MAX_CONCURRENT_FILE_PIPES) - return -1; + return -3; - if (file_sendrequest(m, friendnumber, i, 0, filesize, filename, filename_length) == 0) - return -1; + if (file_sendrequest(m, friendnumber, i, file_type, filesize, filename, filename_length) == 0) + return -4; m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NOT_ACCEPTED; m->friendlist[friendnumber].file_sending[i].size = filesize; m->friendlist[friendnumber].file_sending[i].transferred = 0; + m->friendlist[friendnumber].file_sending[i].type = file_type; return i; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index fa0d241c..ca6b4896 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -129,6 +129,7 @@ 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 */ + unsigned int type; }; enum { FILESTATUS_NONE, @@ -579,10 +580,14 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u /* 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 too big. + * 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 *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. From f5eca31637cbcbdd44f3fefc9139aa8ef0d1bd5e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 9 Mar 2015 20:59:50 -0400 Subject: [PATCH 044/101] Fixed small issue. --- testing/tox_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/tox_shell.c b/testing/tox_shell.c index 5198d224..c8dc9ff2 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -45,7 +45,7 @@ #define c_sleep(x) usleep(1000*x) -void print_online(Tox *tox, uint32_t friendnumber, uint8_t status, void *userdata) +void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata) { if (status) printf("\nOther went online.\n"); From 0207fcdfb0e43d425abb026b08c074a6822e0349 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 10 Mar 2015 17:31:50 -0400 Subject: [PATCH 045/101] Implementation of new api file transfers. Everything should work except resuming. --- auto_tests/tox_test.c | 139 ++++++++---- toxcore/Messenger.c | 500 +++++++++++++++++++++++++++--------------- toxcore/Messenger.h | 74 +++++-- toxcore/tox.c | 167 ++++++++++++++ toxcore/tox.h | 18 +- 5 files changed, 646 insertions(+), 252 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index d7a44fb2..077e51fb 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -21,6 +21,7 @@ #define c_sleep(x) usleep(1000*x) #endif + 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) @@ -83,7 +84,7 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size 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; @@ -92,45 +93,104 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size 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) +void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, uint64_t filesize, + const uint8_t *filename, size_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; + 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; + } file_size = filesize; - tox_file_send_control(m, friendnumber, 1, filenumber, TOX_FILECONTROL_ACCEPT, NULL, 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); + } } -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) +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; - 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) + /* First send file num is 0.*/ + if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) sendf_ok = 1; - } +uint8_t sending_num; +uint64_t sending_pos; +_Bool file_sending_done; +void tox_file_request_chunk(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"); + return; + } + + if (length == 0) { + file_sending_done = 1; + return; + } + + 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, 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"); + } +} + + 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) +_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 *)userdata) != 974536) + 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,7 +198,7 @@ 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"); } } @@ -371,41 +431,32 @@ START_TEST(test_few_clients) c_sleep(50); } - filenum = file_accepted = file_size = file_sent = sendf_ok = size_recv = 0; + file_accepted = file_size = file_recv = sendf_ok = size_recv = 0; long long unsigned int f_time = time(NULL); - tox_callback_file_data(tox3, write_file, &to_compare); + tox_callback_file_receive_chunk(tox3, write_file, &to_compare); tox_callback_file_control(tox2, file_print_control, &to_compare); + tox_callback_file_request_chunk(tox2, tox_file_request_chunk, &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_receive(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, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), + 0); + ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail"); + while (1) { - file_sent = 0; tox_iteration(tox1); tox_iteration(tox2); tox_iteration(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_sending_done) { + if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv) { + break; + } else { + ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u", sendf_ok, file_recv, totalf_size == file_size, + size_recv == file_size, sending_pos == size_recv); } - - if (file_sent && size_recv == file_size) - break; + } uint32_t tox1_interval = tox_iteration_interval(tox1); uint32_t tox2_interval = tox_iteration_interval(tox2); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ee76b103..08b62660 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -349,6 +349,18 @@ static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, new->next = NULL; return 0; } +/* + * return -1 on failure. + * return 0 if packet was received. + */ +static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + return cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), number); +} static int do_receipts(Messenger *m, int32_t friendnumber) { @@ -360,8 +372,7 @@ static int do_receipts(Messenger *m, int32_t friendnumber) while (receipts) { struct Receipts *temp_r = receipts->next; - if (cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, - m->friendlist[friendnumber].friendcon_id), receipts->packet_num) == -1) + if (friend_received_packet(m, friendnumber, receipts->packet_num) == -1) break; if (m->read_receipt) @@ -970,11 +981,11 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uin /* Set the callback for file control requests. * - * Function(Tox *tox, uint32_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, uint32_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) { m->file_filecontrol = function; m->file_filecontrol_userdata = userdata; @@ -982,17 +993,28 @@ void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t /* Set the callback for file data. * - * Function(Tox *tox, uint32_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, uint32_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) { m->file_filedata = function; m->file_filedata_userdata = userdata; } +/* Set the callback for file request chunk. + * + * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata) + * + */ +void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), + void *userdata) +{ + m->file_reqchunk = function; + m->file_reqchunk_userdata = userdata; +} + #define MAX_FILENAME_LENGTH 255 /* Send a file send request. @@ -1053,132 +1075,182 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NOT_ACCEPTED; m->friendlist[friendnumber].file_sending[i].size = filesize; m->friendlist[friendnumber].file_sending[i].transferred = 0; - m->friendlist[friendnumber].file_sending[i].type = file_type; + m->friendlist[friendnumber].file_sending[i].paused = FILE_PAUSE_NOT; + ++m->friendlist[friendnumber].num_sending_files; + return i; } -/* 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 0 on success - * return -1 on failure - */ -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 send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, + uint8_t control_type, uint8_t *data, uint16_t data_length) { - if (length > MAX_CRYPTO_DATA_SIZE - 3) + if (1 + 3 + data_length > MAX_CRYPTO_DATA_SIZE) return -1; + uint8_t packet[3 + data_length]; + + packet[0] = send_receive; + packet[1] = filenumber; + packet[2] = control_type; + + if (data_length) { + memcpy(packet, packet + 3, data_length); + } + + return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, sizeof(packet), 0); +} + +/* Send a 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 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, uint32_t filenumber, unsigned int control) +{ if (friend_not_valid(m, friendnumber)) return -1; - if (send_receive == 1) { - if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE) - return -1; + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -2; + + uint32_t temp_filenum; + uint8_t send_receive, file_number; + + if (filenumber >= (1 << 16)) { + send_receive = 1; + temp_filenum = (filenumber >> 16) - 1; } else { - if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) - return -1; + send_receive = 0; + temp_filenum = filenumber; } - if (send_receive > 1) - return -1; + if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) + return -3; - uint8_t packet[MAX_CRYPTO_DATA_SIZE]; - packet[0] = send_receive; - packet[1] = filenumber; - packet[2] = message_id; - uint64_t transferred = 0; + file_number = temp_filenum; - if (message_id == FILECONTROL_RESUME_BROKEN) { - if (length != sizeof(uint64_t)) - return -1; + struct File_Transfers *ft; - uint8_t remaining[sizeof(uint64_t)]; - memcpy(remaining, data, sizeof(uint64_t)); - host_to_net(remaining, sizeof(uint64_t)); - memcpy(packet + 3, remaining, sizeof(uint64_t)); - memcpy(&transferred, data, sizeof(uint64_t)); + if (send_receive) { + ft = &m->friendlist[friendnumber].file_receiving[file_number]; } else { - memcpy(packet + 3, data, length); + ft = &m->friendlist[friendnumber].file_sending[file_number]; } - if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 3, 0)) { - if (send_receive == 1) - switch (message_id) { - case FILECONTROL_ACCEPT: - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_TRANSFERRING; - break; + if (ft->status == FILESTATUS_NONE) + return -3; - case FILECONTROL_PAUSE: - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_PAUSED_BY_US; - break; + if (control > FILECONTROL_KILL) + return -4; - case FILECONTROL_KILL: - case FILECONTROL_FINISHED: - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_NONE; - break; + if (control == FILECONTROL_PAUSE && (ft->paused & FILE_PAUSE_US)) + return -5; - case FILECONTROL_RESUME_BROKEN: - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_PAUSED_BY_OTHER; - m->friendlist[friendnumber].file_receiving[filenumber].transferred = transferred; - break; + if (control == FILECONTROL_ACCEPT && ft->status == FILESTATUS_TRANSFERRING) { + if (!(ft->paused & FILE_PAUSE_US)) { + if (ft->paused & FILE_PAUSE_OTHER) { + return -6; + } else { + return -7; } - else - switch (message_id) { - case FILECONTROL_ACCEPT: - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_TRANSFERRING; - break; - - case FILECONTROL_PAUSE: - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_PAUSED_BY_US; - break; - - case FILECONTROL_KILL: - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_NONE; - break; - - case FILECONTROL_FINISHED: - break; - } - - return 0; - } else { - return -1; + } } + + if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, 0, 0)) { + if (control == FILECONTROL_KILL) { + ft->status = FILESTATUS_NONE; + + if (send_receive == 0) { + --m->friendlist[friendnumber].num_sending_files; + } + } else if (control == FILECONTROL_PAUSE) { + ft->paused |= FILE_PAUSE_US; + } else if (control == FILECONTROL_ACCEPT) { + ft->status = FILESTATUS_TRANSFERRING; + + if (ft->paused & FILE_PAUSE_US) { + ft->paused ^= FILE_PAUSE_US; + } + } + } else { + return -8; + } + + return 0; } #define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 2) /* Send file data. * * return 0 on success - * return -1 on failure + * 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 trying to send too much data. + * return -6 if packet queue full. */ -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, const uint8_t *data, uint16_t length) { - if (length > MAX_CRYPTO_DATA_SIZE - 1) - return -1; - if (friend_not_valid(m, friendnumber)) return -1; - if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING) - return -1; + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -2; + + if (filenumber > MAX_CONCURRENT_FILE_PIPES) + return -3; + + struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber]; + + if (ft->status != FILESTATUS_TRANSFERRING) + return -4; + + if (ft->paused != FILE_PAUSE_NOT) + return -4; + + if (length > MAX_CRYPTO_DATA_SIZE - 2) + return -5; + + if (ft->size) { + if (ft->size - ft->transferred < length) { + return -5; + } + } /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */ if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) - return -1; + return -6; - uint8_t packet[MAX_CRYPTO_DATA_SIZE]; - packet[0] = filenumber; - memcpy(packet + 1, data, length); + uint8_t packet[2 + length]; + packet[0] = PACKET_ID_FILE_DATA; + packet[1] = filenumber; + memcpy(packet + 2, data, length); + + int64_t ret = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), packet, sizeof(packet), 1); + + if (ret != -1) { + //TODO record packet ids to check if other received complete file. + ft->transferred += length; + + if (length == 0 || ft->size == ft->transferred) { + ft->status = FILESTATUS_FINISHED; + ft->last_packet_number = ret; + } - if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1, 1)) { - m->friendlist[friendnumber].file_sending[filenumber].transferred += length; return 0; } - return -1; + return -6; } @@ -1209,105 +1281,142 @@ uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t fi } } +static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) +{ + if (!m->friendlist[friendnumber].num_sending_files) + return; + + int free_slots = crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id)); + + if (free_slots <= MIN_SLOTS_FREE) + return; + + free_slots -= MIN_SLOTS_FREE; + + unsigned int i, num = m->friendlist[friendnumber].num_sending_files; + + for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { + struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; + + if (ft->status != FILESTATUS_NONE) { + --num; + + if (ft->status == FILESTATUS_FINISHED) { + /* Check if file was entirely sent. */ + if (friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) { + if (m->file_reqchunk) + (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, 0, m->file_reqchunk_userdata); + + ft->status = FILESTATUS_NONE; + --m->friendlist[friendnumber].num_sending_files; + } + } + } + + while (ft->status == FILESTATUS_TRANSFERRING && (ft->paused == FILE_PAUSE_NOT)) { + if (free_slots == 0) + break; + + uint16_t length = MAX_CRYPTO_DATA_SIZE - 2; + + if (ft->size) { + if (ft->size == ft->transferred) { + break; + } + + if (ft->size - ft->transferred < length) { + length = ft->size - ft->transferred; + } + } + + if (m->file_reqchunk) + (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, length, m->file_reqchunk_userdata); + + --free_slots; + } + + if (num == 0) + break; + } +} + /* Run this when the friend disconnects. * Sets all current file transfers to broken. */ static void break_files(const Messenger *m, int32_t friendnumber) { uint32_t i; + /* TODO + for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { + if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) + m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_BROKEN; - for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { - if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) - m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_BROKEN; - - if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) - m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_BROKEN; - } + if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) + m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_BROKEN; + }*/ } -static int handle_filecontrol(const Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, - uint8_t message_id, uint8_t *data, - uint16_t length) +/* return -1 on failure, 0 on success. + */ +static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, + uint8_t control_type, uint8_t *data, uint16_t length) { if (receive_send > 1) return -1; + if (control_type > FILECONTROL_RESUME_BROKEN) + return -1; + + uint32_t real_filenumber = filenumber; + struct File_Transfers *ft; + if (receive_send == 0) { - if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE) { - /* Tell the other to kill the file sending if we don't know this one. */ - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_TEMPORARY; - file_control(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, NULL, 0); - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_NONE; - return -1; - - } - - switch (message_id) { - case FILECONTROL_ACCEPT: - if (m->friendlist[friendnumber].file_receiving[filenumber].status != FILESTATUS_PAUSED_BY_US) { - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_TRANSFERRING; - return 0; - } - - return -1; - - case FILECONTROL_PAUSE: - if (m->friendlist[friendnumber].file_receiving[filenumber].status != FILESTATUS_PAUSED_BY_US) { - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_PAUSED_BY_OTHER; - return 0; - } - - return -1; - - case FILECONTROL_KILL: - m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_NONE; - - case FILECONTROL_FINISHED: - return 0; - } + real_filenumber += 1; + real_filenumber <<= 16; + ft = &m->friendlist[friendnumber].file_receiving[filenumber]; } else { - if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) { - /* Tell the other to kill the file sending if we don't know this one. */ - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_TEMPORARY; - file_control(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, NULL, 0); - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_NONE; - return -1; - } - - switch (message_id) { - case FILECONTROL_ACCEPT: - if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_PAUSED_BY_US) { - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_TRANSFERRING; - return 0; - } - - return -1; - - case FILECONTROL_PAUSE: - if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_PAUSED_BY_US) { - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_PAUSED_BY_OTHER; - } - - return 0; - - case FILECONTROL_KILL: - case FILECONTROL_FINISHED: - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_NONE; - return 0; - - case FILECONTROL_RESUME_BROKEN: { - if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_BROKEN && length == sizeof(uint64_t)) { - m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_PAUSED_BY_US; - net_to_host(data, sizeof(uint64_t)); - return 0; - } - - return -1; - } - } + ft = &m->friendlist[friendnumber].file_sending[filenumber]; } - return -1; + if (ft->status == FILESTATUS_NONE) { + /* File transfer doesn't exist, tell the other to kill it. */ + send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0); + return -1; + } + + if (control_type == FILECONTROL_ACCEPT) { + ft->status = FILESTATUS_TRANSFERRING; + + if (ft->paused & FILE_PAUSE_OTHER) { + ft->paused ^= FILE_PAUSE_OTHER; + } + + if (m->file_filecontrol) + (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata); + } else if (control_type == FILECONTROL_PAUSE) { + ft->paused |= FILE_PAUSE_OTHER; + + if (m->file_filecontrol) + (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata); + } else if (control_type == FILECONTROL_KILL) { + + if (m->file_filecontrol) + (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata); + + ft->status = FILESTATUS_NONE; + + if (receive_send) { + --m->friendlist[friendnumber].num_sending_files; + } + + } else if (control_type == FILECONTROL_RESUME_BROKEN) { + //TODO + } else { + return -1; + } + + return 0; } /**************************************/ @@ -1766,6 +1875,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; m->friendlist[i].file_receiving[filenumber].size = filesize; m->friendlist[i].file_receiving[filenumber].transferred = 0; + m->friendlist[i].file_receiving[filenumber].paused = FILE_PAUSE_NOT; /* Force NULL terminate file name. */ uint8_t filename_terminated[data_length - head_length + 1]; @@ -1794,26 +1904,51 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) break; - if (m->file_filecontrol) - (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, - m->file_filecontrol_userdata); - break; } case PACKET_ID_FILE_DATA: { - if (data_length < 2) + if (data_length <= 1) break; uint8_t filenumber = data[0]; + struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; - if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) + if (ft->status == FILESTATUS_NONE) break; - m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); + uint64_t position = ft->transferred; + uint32_t real_filenumber = filenumber; + real_filenumber += 1; + real_filenumber <<= 16; + uint16_t file_data_length = (data_length - 1); + uint8_t *file_data; + + if (file_data_length == 0) { + file_data = NULL; + } else { + file_data = data + 1; + } if (m->file_filedata) - (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); + (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, m->file_filedata_userdata); + + ft->transferred += file_data_length; + + if (ft->size && ft->transferred >= ft->size) { + file_data_length = 0; + file_data = NULL; + position = ft->transferred; + + /* Full file received. */ + if (m->file_filedata) + (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, m->file_filedata_userdata); + } + + /* Data is zero, filetransfer is over. */ + if (file_data_length == 0) { + ft->status = FILESTATUS_NONE; + } break; } @@ -1907,6 +2042,7 @@ void do_friends(Messenger *m) check_friend_tcp_udp(m, i); do_receipts(m, i); + do_reqchunk_filecb(m, i); } } } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index ca6b4896..5215f989 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -128,18 +128,25 @@ USERSTATUS; 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 */ - unsigned int type; + 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. */ }; 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 @@ -147,7 +154,6 @@ enum { FILECONTROL_ACCEPT, FILECONTROL_PAUSE, FILECONTROL_KILL, - FILECONTROL_FINISHED, FILECONTROL_RESUME_BROKEN }; @@ -179,6 +185,7 @@ typedef struct { 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]; struct { @@ -249,10 +256,12 @@ struct Messenger { void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, unsigned int, uint64_t, const uint8_t *, size_t, void *); void *file_sendrequest_userdata; - void (*file_filecontrol)(struct Messenger *m, uint32_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, uint32_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, uint32_t, const uint8_t *, uint16_t, void *); void *msi_packet_userdata; @@ -562,20 +571,27 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uin /* Set the callback for file control requests. * - * Function(Tox *tox, uint32_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, uint32_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, uint32_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, uint32_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); + +/* Set the callback for file request chunk. + * + * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata) + * + */ +void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), + void *userdata); /* Send a file send request. * Maximum filename length is 255 bytes. @@ -590,20 +606,30 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ 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 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 trying to send too much data. + * return -6 if packet queue full. */ -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, const uint8_t *data, uint16_t length); /* Give the number of bytes left to be sent/received. * diff --git a/toxcore/tox.c b/toxcore/tox.c index fc6ffc2b..bcb871fc 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -811,6 +811,173 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * m_callback_action(m, function, user_data); } +bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) +{ + if (!hash || !data) { + return 0; + } + + crypto_hash_sha256(hash, data, length); + return 1; +} + +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, + TOX_ERR_FILE_CONTROL *error) +{ + Messenger *m = tox; + int ret = file_control(m, friend_number, file_number, control); + + if (ret == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK); + return 1; + } + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND); + return 0; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED); + return 0; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_FOUND); + return 0; + + case -4: + /* can't happen */ + return 0; + + case -5: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_ALREADY_PAUSED); + return 0; + + case -6: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_DENIED); + return 0; + + case -7: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_PAUSED); + return 0; + + case -8: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SEND_FAILED); + return 0; + } + + /* can't happen */ + return 0; +} + +void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *user_data) +{ + Messenger *m = tox; + callback_file_control(m, function, user_data); +} + +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, + const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) +{ + if (!filename) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); + return UINT32_MAX; + } + + if (!filename_length) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_EMPTY); + return UINT32_MAX; + } + + Messenger *m = tox; + long int file_num = new_filesender(m, friend_number, kind, file_size, filename, filename_length); + + if (file_num >= 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); + return file_num; + } + + switch (file_num) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND); + return UINT32_MAX; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG); + return UINT32_MAX; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_TOO_MANY); + return UINT32_MAX; + + case -4: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED); + return UINT32_MAX; + } + + /* can't happen */ + return UINT32_MAX; +} + +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, const uint8_t *data, size_t length, + TOX_ERR_FILE_SEND_CHUNK *error) +{ + Messenger *m = tox; + int ret = file_data(m, friend_number, file_number, data, length); + + if (ret == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK); + return 1; + } + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND); + return 0; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED); + return 0; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND); + return 0; + + case -4: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING); + return 0; + + case -5: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE); + return 0; + + case -6: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL); + return 0; + } + + /* can't happen */ + return 0; +} + +void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *function, void *user_data) +{ + Messenger *m = tox; + callback_file_reqchunk(m, function, user_data); +} + +void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *user_data) +{ + Messenger *m = tox; + callback_file_sendrequest(m, function, user_data); +} + +void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *function, void *user_data) +{ + Messenger *m = tox; + callback_file_data(m, function, user_data); +} + static void set_custom_packet_error(int ret, TOX_ERR_SEND_CUSTOM_PACKET *error) { switch (ret) { diff --git a/toxcore/tox.h b/toxcore/tox.h index 23d37cd9..b8cac443 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1485,7 +1485,11 @@ typedef enum TOX_ERR_FILE_CONTROL { /** * A PAUSE control was sent, but the file transfer was already paused. */ - TOX_ERR_FILE_CONTROL_ALREADY_PAUSED + TOX_ERR_FILE_CONTROL_ALREADY_PAUSED, + /** + * Packet failed to send. + */ + TOX_ERR_FILE_CONTROL_SEND_FAILED } TOX_ERR_FILE_CONTROL; /** @@ -1612,6 +1616,7 @@ typedef enum TOX_ERR_FILE_SEND { * * @return A file number used as an identifier in subsequent callbacks. This * number is per friend. File numbers are reused after a transfer terminates. + * on failure, this function returns UINT32_MAX. */ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); @@ -1635,12 +1640,21 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * No file transfer with the given file number was found for the given friend. */ TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND, + /** + * File transfer was found but isn't in a transferring state: (paused, done, + * broken, etc...) (happens only when not called from the request chunk callback). + */ + TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING, /** * Attempted to send more data than requested. The requested data size is * adjusted according to maximum transmission unit and the expected end of * the file. Trying to send more will result in no data being sent. */ - TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE + TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE, + /** + * Packet queue is full. + */ + TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL } TOX_ERR_FILE_SEND_CHUNK; /** From c434d4857993668ed78668f2edbef29744740fd3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 10 Mar 2015 18:29:10 -0400 Subject: [PATCH 046/101] testing/tox_sync now fully works on the new api. --- testing/tox_sync.c | 112 +++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 49 deletions(-) diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 77f75c36..785fffeb 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -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_request_chunk(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, 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, (uint8_t *)filename, strlen(filename) + 1, + 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, TOX_FILE_KIND 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,48 +151,62 @@ 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, uint32_t friendnumber, uint8_t status, void *userdata) +void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata) { if (status) printf("\nOther went online.\n"); @@ -215,9 +229,10 @@ int main(int argc, char *argv[]) } Tox *tox = tox_new(0, 0, 0, 0); - tox_callback_file_data(tox, write_file, NULL); + tox_callback_file_receive_chunk(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_file_receive(tox, file_request_accept, NULL); + tox_callback_file_request_chunk(tox, tox_file_request_chunk, NULL); tox_callback_friend_connection_status(tox, print_online, NULL); uint16_t port = atoi(argv[argvoffset + 2]); @@ -290,7 +305,6 @@ int main(int argc, char *argv[]) } } - send_filesenders(tox); tox_iteration(tox); c_sleep(1); } From 8e55d96381cca3b1ca9db18bac715ba2e8a6f558 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 10 Mar 2015 18:49:06 -0400 Subject: [PATCH 047/101] Ported nTox to new file transfer api. --- testing/nTox.c | 117 +++++++++++++++++++++++++-------------------- testing/tox_sync.c | 1 + 2 files changed, 67 insertions(+), 51 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index ff419c9a..708397f9 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -112,48 +112,45 @@ typedef struct { 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_request_chunk(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, 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, (uint8_t *)filename, strlen(filename) + 1, + 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; @@ -1132,48 +1127,68 @@ 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, TOX_FILE_KIND 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"); @@ -1254,9 +1269,10 @@ int main(int argc, char *argv[]) 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_receive_chunk(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_receive(m, file_request_accept, NULL); + tox_callback_file_request_chunk(m, tox_file_request_chunk, NULL); tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL); initscr(); @@ -1310,7 +1326,6 @@ int main(int argc, char *argv[]) } } - send_filesenders(m); tox_iteration(m); do_refresh(); diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 785fffeb..bdbd2e3f 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -190,6 +190,7 @@ void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t p size_t length, void *user_data) { uint8_t file_index = (filenumber >> 16) - 1; + if (length == 0) { fclose(file_recv[file_index].file); printf("File closed\n"); From 916b6aa7344ed922c3f8da04e7b2d73e2ee65411 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 10 Mar 2015 18:54:01 -0400 Subject: [PATCH 048/101] Added group chat functions to the public api. Since the functions are not new api like I put them in tox_old.{c,h} --- toxcore/tox.c | 3 + toxcore/tox.h | 2 + toxcore/tox_old.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ toxcore/tox_old.h | 173 +++++++++++++++++++++++++++++++++ 4 files changed, 415 insertions(+) create mode 100644 toxcore/tox_old.c create mode 100644 toxcore/tox_old.h diff --git a/toxcore/tox.c b/toxcore/tox.c index bcb871fc..80cbb71d 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1075,3 +1075,6 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb Messenger *m = tox; custom_lossless_packet_registerhandler(m, function, user_data); } + + +#include "tox_old.c" diff --git a/toxcore/tox.h b/toxcore/tox.h index b8cac443..5323c4b6 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1785,6 +1785,7 @@ void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *functi * ******************************************************************************/ +/* See: tox_old.h for now. */ /******************************************************************************* * @@ -1940,6 +1941,7 @@ uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error); */ uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); +#include "tox_old.h" #ifdef __cplusplus } diff --git a/toxcore/tox_old.c b/toxcore/tox_old.c new file mode 100644 index 00000000..2a422575 --- /dev/null +++ b/toxcore/tox_old.c @@ -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); +} diff --git a/toxcore/tox_old.h b/toxcore/tox_old.h new file mode 100644 index 00000000..a926cdf7 --- /dev/null +++ b/toxcore/tox_old.h @@ -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); + From 88a8a079b6601d09fadca9b80a23cef3c5232eb9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 11 Mar 2015 08:09:45 -0400 Subject: [PATCH 049/101] Implemented the 3 low level network information functions. Added tox_get_udp_port() to tests. --- auto_tests/tox_test.c | 25 +++++++++++++++++++++++++ toxcore/tox.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 077e51fb..d3f9472a 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -207,6 +207,12 @@ START_TEST(test_one) Tox *tox1 = tox_new(0, 0, 0, 0); Tox *tox2 = tox_new(0, 0, 0, 0); + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_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"); + } + uint8_t address[TOX_ADDRESS_SIZE]; tox_self_get_address(tox1, address); TOX_ERR_FRIEND_ADD error; @@ -272,6 +278,13 @@ START_TEST(test_few_clients) Tox *tox2 = tox_new(0, 0, 0, 0); Tox *tox3 = tox_new(0, 0, 0, 0); ck_assert_msg(tox1 || tox2 || tox3, "Failed to create 3 tox instances"); + + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_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"); + } + uint32_t to_compare = 974536; tox_callback_friend_request(tox2, accept_friend_request, &to_compare); uint8_t address[TOX_ADDRESS_SIZE]; @@ -495,6 +508,12 @@ START_TEST(test_many_clients) tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); } + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_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; @@ -617,6 +636,12 @@ START_TEST(test_many_group) tox_callback_group_invite(toxes[i], &print_group_invite_callback, &to_comp); } + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_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); diff --git a/toxcore/tox.c b/toxcore/tox.c index 80cbb71d..066fd33d 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1076,5 +1076,33 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb custom_lossless_packet_registerhandler(m, function, user_data); } +void tox_get_dht_id(const Tox *tox, uint8_t *dht_id) +{ + if (dht_id) { + const Messenger *m = tox; + memcpy(dht_id , m->dht->self_public_key, crypto_box_PUBLICKEYBYTES); + } +} + +uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) +{ + const Messenger *m = tox; + uint16_t port = htons(m->net->port); + + if (port) { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); + } + + return port; +} + +uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) +{ + /* TCP server not yet implemented in clients. */ + SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); + return 0; +} #include "tox_old.c" From 572484f06ec75df61960077b033a9c7e4d28d283 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 11 Mar 2015 13:51:11 -0400 Subject: [PATCH 050/101] Use .h for tox_old instead of .c to not break some of my build commands. --- toxcore/tox.c | 2 +- toxcore/{tox_old.c => tox_old_code.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename toxcore/{tox_old.c => tox_old_code.h} (100%) diff --git a/toxcore/tox.c b/toxcore/tox.c index 066fd33d..6bb20c81 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1105,4 +1105,4 @@ uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) return 0; } -#include "tox_old.c" +#include "tox_old_code.h" diff --git a/toxcore/tox_old.c b/toxcore/tox_old_code.h similarity index 100% rename from toxcore/tox_old.c rename to toxcore/tox_old_code.h From 43fe6e71bd06dd4fcc2bb49662f56b493ed9b6fc Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 11 Mar 2015 15:37:25 -0400 Subject: [PATCH 051/101] tox_callback_connection_status() implemented. Attempted fix of connection checking to make it more stable. --- auto_tests/tox_test.c | 34 +++++++++---- toxcore/Messenger.c | 17 +++++++ toxcore/Messenger.h | 9 ++++ toxcore/onion_client.c | 113 ++++++++++++++++++++++++++--------------- toxcore/onion_client.h | 8 ++- toxcore/tox.c | 15 +++--- 6 files changed, 137 insertions(+), 59 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index d3f9472a..7cae9da6 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -202,6 +202,18 @@ void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t p } } +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, 0, 0, 0); @@ -286,6 +298,8 @@ START_TEST(test_few_clients) } uint32_t to_compare = 974536; + connected_t1 = 0; + tox_callback_connection_status(tox1, tox_connection_status, &to_compare); tox_callback_friend_request(tox2, accept_friend_request, &to_compare); uint8_t address[TOX_ADDRESS_SIZE]; tox_self_get_address(tox2, address); @@ -299,20 +313,22 @@ START_TEST(test_few_clients) tox_iteration(tox2); tox_iteration(tox3); - if (tox_get_connection_status(tox1) && tox_get_connection_status(tox2) && tox_get_connection_status(tox3) && off) { - printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); - con_time = time(NULL); - off = 0; + if (tox_get_connection_status(tox1) && tox_get_connection_status(tox2) && tox_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_friend_get_connection_status(tox2, 0, 0) == TOX_CONNECTION_UDP + && tox_friend_get_connection_status(tox3, 0, 0) == TOX_CONNECTION_UDP) + break; } - - 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); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 08b62660..546fe4a8 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -865,6 +865,12 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, ui m->friend_connectionstatuschange_userdata = userdata; } +void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata) +{ + m->core_connection_change = function; + m->core_connection_change_userdata = userdata; +} + void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), void *userdata) { @@ -2047,7 +2053,17 @@ void do_friends(Messenger *m) } } +static void connection_status_cb(Messenger *m) +{ + unsigned int conn_status = onion_connection_status(m->onion_c); + if (conn_status != m->last_connection_status) { + if (m->core_connection_change) + (*m->core_connection_change)(m, conn_status, m->core_connection_change_userdata); + + m->last_connection_status = conn_status; + } +} #ifdef LOGGING @@ -2112,6 +2128,7 @@ void do_messenger(Messenger *m) do_friend_connections(m->fr_c); do_friends(m); LANdiscovery(m); + connection_status_cb(m); #ifdef LOGGING diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 5215f989..ae80760f 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -271,6 +271,10 @@ struct Messenger { 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; }; @@ -543,6 +547,11 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess void *userdata); +/* Set the callback for typing changes. + * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP)) + */ +void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata); + /**********GROUP CHATS************/ /* Set the callback for group invites. diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 3643cb2f..a9fc1643 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -1351,6 +1351,64 @@ static void do_announce(Onion_Client *onion_c) } } +/* return 0 if we are not connected to the network. + * return 1 if we are. + */ +static int onion_isconnected(const Onion_Client *onion_c) +{ + unsigned int i, num = 0, announced = 0; + + if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) + return 0; + + if (onion_c->path_nodes_index == 0) + return 0; + + for (i = 0; i < MAX_ONION_CLIENTS; ++i) { + if (!is_timeout(onion_c->clients_announce_list[i].timestamp, ONION_NODE_TIMEOUT)) { + ++num; + + if (onion_c->clients_announce_list[i].is_stored) { + ++announced; + } + } + } + + unsigned int pnodes = onion_c->path_nodes_index; + + if (pnodes > MAX_ONION_CLIENTS) { + pnodes = MAX_ONION_CLIENTS; + } + + /* Consider ourselves online if we are announced to half or more nodes + we are connected to */ + if (num && announced) { + if ((num / 2) <= announced && (pnodes / 2) <= num) + return 1; + } + + 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; @@ -1363,11 +1421,23 @@ void do_onion_client(Onion_Client *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); } - } else { - populate_path_nodes_tcp(onion_c); } onion_c->last_run = unix_time(); @@ -1418,42 +1488,3 @@ void kill_onion_client(Onion_Client *onion_c) 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) -{ - unsigned int i, num = 0, announced = 0; - - if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) - return 0; - - if (onion_c->path_nodes_index == 0) - return 0; - - for (i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (!is_timeout(onion_c->clients_announce_list[i].timestamp, ONION_NODE_TIMEOUT)) { - ++num; - - if (onion_c->clients_announce_list[i].is_stored) { - ++announced; - } - } - } - - unsigned int pnodes = onion_c->path_nodes_index; - - if (pnodes > MAX_ONION_CLIENTS) { - pnodes = MAX_ONION_CLIENTS; - } - - /* Consider ourselves online if we are announced to half or more nodes - we are connected to */ - if (num && announced) { - if ((num / 2) <= announced && (pnodes / 2) <= num) - return 1; - } - - return 0; -} diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 6851d929..e10a86c5 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -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 diff --git a/toxcore/tox.c b/toxcore/tox.c index 6bb20c81..554414b1 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -278,21 +278,22 @@ TOX_CONNECTION tox_get_connection_status(const Tox *tox) { const Messenger *m = tox; - if (onion_isconnected(m->onion_c)) { - if (DHT_non_lan_connected(m->dht)) { - return TOX_CONNECTION_UDP; - } + unsigned int ret = onion_connection_status(m->onion_c); + if (ret == 2) { + return TOX_CONNECTION_UDP; + } else if (ret == 1) { return TOX_CONNECTION_TCP; + } else { + return TOX_CONNECTION_NONE; } - - return TOX_CONNECTION_NONE; } void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function, void *user_data) { - //TODO + Messenger *m = tox; + m_callback_core_connection(m, function, user_data); } uint32_t tox_iteration_interval(const Tox *tox) From 91274495bc1e24bbab039e0e468be14fa34caf23 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sat, 28 Feb 2015 15:26:19 -0600 Subject: [PATCH 052/101] This is a combination of 11 commits. The first commit's message is: TOX_STATUS -> TOX_USER_STATUS, is more specific This is the 2nd commit message: I pretty strongly believe tox_iteration needs to be renamed to a verb There are several other noun functions in the API, but none of them *do* things. I think even tox_do is better than tox_iteration. tox_do_interval is one possibility, but I'm open to suggestions. This is the 3rd commit message: private_key -> secret_key This is more consistent with modern/NaCl/elliptic cryptography, and also "pk", meaning public key, is all over other toxcore code and documentation. This will eliminate ambiguity. This is the 4th commit message: Rename some functions for pseudo-namespace consistency The enum change results in long enum types, but I think consistency trumps having a few less characters. This is the 5th commit message: TOX_FILE_KIND -> TOX_FILE_TYPE This is more of an English thing than a consistency thing, but TOX_FILE_KIND sounds funnier/stranger to me than TOX_FILE_TYPE. This is the 6th commit message: More specific file control function names This is the 7th commit message: Rename custom packet functions for pseudo-namespace consistency This also has the issue with long enums... but I still think consistent enum names are better This is the 8th commit message: Rename functions for pseudo-namespace consistency This is the 9th commit message: Consistency with https://github.com/sonOfRa/tox4j/blob/master/doc/core-design.md#naming-conventions and the rest of the api This is the 10th commit message: Fix errors in previous function rename commits This is the 11th commit message: Shorten one error enum name --- toxcore/tox.c | 76 ++++++++++++++++----------------- toxcore/tox.h | 114 +++++++++++++++++++++++++------------------------- 2 files changed, 95 insertions(+), 95 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 554414b1..9a821bfb 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -411,13 +411,13 @@ void tox_self_get_status_message(const Tox *tox, uint8_t *status) } } -void tox_self_set_status(Tox *tox, TOX_STATUS user_status) +void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status) { Messenger *m = tox; m_set_userstatus(m, user_status); } -TOX_STATUS tox_self_get_status(const Tox *tox) +TOX_USER_STATUS tox_self_get_status(const Tox *tox) { const Messenger *m = tox; return m_get_self_userstatus(m); @@ -561,7 +561,7 @@ size_t tox_friend_list_size(const Tox *tox) return count_friendlist(m); } -void tox_friend_list(const Tox *tox, uint32_t *list) +void tox_friend_get_list(const Tox *tox, uint32_t *list) { if (list) { const Messenger *m = tox; @@ -650,7 +650,7 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb * m_callback_statusmessage(m, function, user_data); } -TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) +TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { const Messenger *m = tox; @@ -658,7 +658,7 @@ TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR if (ret == USERSTATUS_INVALID) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); - return TOX_STATUS_INVALID; + return TOX_USER_STATUS_INVALID; } SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); @@ -725,41 +725,41 @@ bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_E return 1; } -static void set_message_error(int ret, TOX_ERR_SEND_MESSAGE *error) +static void set_message_error(int ret, TOX_ERR_FRIEND_SEND_MESSAGE *error) { switch (ret) { case 0: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_OK); break; case -1: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_FRIEND_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND); break; case -2: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_TOO_LONG); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG); break; case -3: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_FRIEND_NOT_CONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED); break; case -4: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_SENDQ); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ); break; } } -uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, - TOX_ERR_SEND_MESSAGE *error) +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, + TOX_ERR_FRIEND_SEND_MESSAGE *error) { if (!message) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_NULL); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL); return 0; } if (!length) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_EMPTY); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY); return 0; } @@ -769,16 +769,16 @@ uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *messa return message_id; } -uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, - TOX_ERR_SEND_MESSAGE *error) +uint32_t tox_friend_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, + TOX_ERR_FRIEND_SEND_MESSAGE *error) { if (!action) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_NULL); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL); return 0; } if (!length) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_MESSAGE_EMPTY); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY); return 0; } @@ -788,7 +788,7 @@ uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action return message_id; } -void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *user_data) +void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function, void *user_data) { Messenger *m = tox; m_callback_read_receipt(m, function, user_data); @@ -871,13 +871,13 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TO return 0; } -void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *user_data) +void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data) { Messenger *m = tox; callback_file_control(m, function, user_data); } -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_TYPE kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) { if (!filename) { @@ -979,52 +979,52 @@ void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *functi callback_file_data(m, function, user_data); } -static void set_custom_packet_error(int ret, TOX_ERR_SEND_CUSTOM_PACKET *error) +static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error) { switch (ret) { case 0: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_OK); break; case -1: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND); break; case -2: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_TOO_LONG); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG); break; case -3: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_INVALID); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID); break; case -4: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED); break; case -5: - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_SENDQ); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ); break; } } -bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, - TOX_ERR_SEND_CUSTOM_PACKET *error) +bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_FRIEND_CUSTOM_PACKET *error) { if (!data) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_NULL); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL); return 0; } Messenger *m = tox; if (length == 0) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_EMPTY); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY); return 0; } if (data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_INVALID); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID); return 0; } @@ -1045,18 +1045,18 @@ void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *func custom_lossy_packet_registerhandler(m, function, user_data); } -bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, - TOX_ERR_SEND_CUSTOM_PACKET *error) +bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_FRIEND_CUSTOM_PACKET *error) { if (!data) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_NULL); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL); return 0; } Messenger *m = tox; if (length == 0) { - SET_ERROR_PARAMETER(error, TOX_ERR_SEND_CUSTOM_PACKET_EMPTY); + SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY); return 0; } diff --git a/toxcore/tox.h b/toxcore/tox.h index 5323c4b6..c4309e59 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -260,26 +260,26 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); /** * Represents the possible statuses a client can have. */ -typedef enum TOX_STATUS { +typedef enum TOX_USER_STATUS { /** * User is online and available. */ - TOX_STATUS_NONE, + TOX_USER_STATUS_NONE, /** * User is away. Clients can set this e.g. after a user defined * inactivity time. */ - TOX_STATUS_AWAY, + TOX_USER_STATUS_AWAY, /** * User is busy. Signals to other clients that this client does not * currently wish to communicate. */ - TOX_STATUS_BUSY, + TOX_USER_STATUS_BUSY, /** * Invalid status used when function returns an error. */ - TOX_STATUS_INVALID -} TOX_STATUS; + TOX_USER_STATUS_INVALID +} TOX_USER_STATUS; /******************************************************************************* @@ -652,7 +652,7 @@ uint32_t tox_iteration_interval(const Tox *tox); * The main loop that needs to be run in intervals of tox_iteration_interval() * milliseconds. */ -void tox_iteration(Tox *tox); +void tox_do_iteration(Tox *tox); /******************************************************************************* @@ -695,12 +695,12 @@ uint32_t tox_self_get_nospam(const Tox *tox); void tox_self_get_public_key(const Tox *tox, uint8_t *public_key); /** - * Copy the private key from the Tox object. + * Copy the secret key from the Tox object. * - * @param private_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If + * @param secret_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If * this parameter is NULL, this function has no effect. */ -void tox_self_get_private_key(const Tox *tox, uint8_t *private_key); +void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key); /******************************************************************************* @@ -801,12 +801,12 @@ void tox_self_get_status_message(const Tox *tox, uint8_t *status); * * @param user_status One of the user statuses listed in the enumeration above. */ -void tox_self_set_status(Tox *tox, TOX_STATUS user_status); +void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status); /** * Returns the client's user status. */ -TOX_STATUS tox_self_get_status(const Tox *tox); +TOX_USER_STATUS tox_self_get_status(const Tox *tox); /******************************************************************************* @@ -992,7 +992,7 @@ size_t tox_friend_list_size(const Tox *tox); * @param list A memory region with enough space to hold the friend list. If * this parameter is NULL, this function has no effect. */ -void tox_friend_list(const Tox *tox, uint32_t *list); +void tox_friend_get_list(const Tox *tox, uint32_t *list); @@ -1114,7 +1114,7 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb * * The status returned is equal to the last status received through the * `friend_status` callback. */ -TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); /** * The function type for the `friend_status` callback. @@ -1123,7 +1123,7 @@ TOX_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR * changed. * @param status The new user status. */ -typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_STATUS status, void *user_data); +typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_USER_STATUS status, void *user_data); /** * Set the callback for the `friend_status` event. Pass NULL to unset. @@ -1228,30 +1228,30 @@ typedef enum TOX_ERR_SET_TYPING { bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error); -typedef enum TOX_ERR_SEND_MESSAGE { - TOX_ERR_SEND_MESSAGE_OK, - TOX_ERR_SEND_MESSAGE_NULL, +typedef enum TOX_ERR_FRIEND_SEND_MESSAGE { + TOX_ERR_FRIEND_SEND_MESSAGE_OK, + TOX_ERR_FRIEND_SEND_MESSAGE_NULL, /** * The friend number did not designate a valid friend. */ - TOX_ERR_SEND_MESSAGE_FRIEND_NOT_FOUND, + TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND, /** * This client is currently not connected to the friend. */ - TOX_ERR_SEND_MESSAGE_FRIEND_NOT_CONNECTED, + TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED, /** * An allocation error occurred while increasing the send queue size. */ - TOX_ERR_SEND_MESSAGE_SENDQ, + TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ, /** * Message length exceeded TOX_MAX_MESSAGE_LENGTH. */ - TOX_ERR_SEND_MESSAGE_TOO_LONG, + TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG, /** * Attempted to send a zero-length message. */ - TOX_ERR_SEND_MESSAGE_EMPTY -} TOX_ERR_SEND_MESSAGE; + TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY +} TOX_ERR_FRIEND_SEND_MESSAGE; /** * Send a text chat message to an online friend. @@ -1270,8 +1270,8 @@ typedef enum TOX_ERR_SEND_MESSAGE { * incremented by 1 each time a message is sent. If UINT32_MAX messages were * sent, the next message ID is 0. */ -uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, - TOX_ERR_SEND_MESSAGE *error); +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, + TOX_ERR_FRIEND_SEND_MESSAGE *error); /** @@ -1283,10 +1283,10 @@ uint32_t tox_send_message(Tox *tox, uint32_t friend_number, const uint8_t *messa * means that sending a message will cause the next message ID from sending an * action will be incremented. * - * @see tox_send_message for more details. + * @see tox_friend_send_message for more details. */ -uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, - TOX_ERR_SEND_MESSAGE *error); +uint32_t tox_friend_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, + TOX_ERR_FRIEND_SEND_MESSAGE *error); /** @@ -1296,7 +1296,7 @@ uint32_t tox_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action * @param message_id The message ID as returned from tox_send_message or * tox_send_action corresponding to the message sent. */ -typedef void tox_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data); +typedef void tox_friend_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data); /** * Set the callback for the `read_receipt` event. Pass NULL to unset. @@ -1307,7 +1307,7 @@ typedef void tox_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t mess * received here may not correspond to any message sent through tox_send_message * or tox_send_action. In that case, the receipt should be discarded. */ -void tox_callback_read_receipt(Tox *tox, tox_read_receipt_cb *function, void *user_data); +void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function, void *user_data); /******************************************************************************* @@ -1390,12 +1390,12 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * ******************************************************************************/ -typedef enum TOX_FILE_KIND { +typedef enum TOX_FILE_TYPE { /** * Arbitrary file data. Clients can choose to handle it based on the file name * or magic or any other way they choose. */ - TOX_FILE_KIND_DATA, + TOX_FILE_TYPE_DATA, /** * Avatar data. This consists of tox_hash(image) + image. * @@ -1412,8 +1412,8 @@ typedef enum TOX_FILE_KIND { * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar * transfer if it matches. */ - TOX_FILE_KIND_AVATAR -} TOX_FILE_KIND; + TOX_FILE_TYPE_AVATAR +} TOX_FILE_TYPE; /** @@ -1502,7 +1502,7 @@ typedef enum TOX_ERR_FILE_CONTROL { * * @return true on success. */ -bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, +bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, TOX_ERR_FILE_CONTROL *error); @@ -1517,7 +1517,7 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TO * associated with. * @param control The file control command received. */ -typedef void tox_file_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, +typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, void *user_data); /** @@ -1526,7 +1526,7 @@ typedef void tox_file_control_cb(Tox *tox, uint32_t friend_number, uint32_t file * This event is triggered when a file control command is received from a * friend. */ -void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *user_data); +void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); /******************************************************************************* @@ -1618,7 +1618,7 @@ typedef enum TOX_ERR_FILE_SEND { * number is per friend. File numbers are reused after a transfer terminates. * on failure, this function returns UINT32_MAX. */ -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_TYPE kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); @@ -1731,7 +1731,7 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi * @param file_number The friend-specific file number the data received is * associated with. */ -typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, +typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); /** @@ -1794,35 +1794,35 @@ void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *functi ******************************************************************************/ -typedef enum TOX_ERR_SEND_CUSTOM_PACKET { - TOX_ERR_SEND_CUSTOM_PACKET_OK, - TOX_ERR_SEND_CUSTOM_PACKET_NULL, +typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET { + TOX_ERR_FRIEND_CUSTOM_PACKET_OK, + TOX_ERR_FRIEND_CUSTOM_PACKET_NULL, /** * The friend number did not designate a valid friend. */ - TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_FOUND, + TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND, /** * This client is currently not connected to the friend. */ - TOX_ERR_SEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED, + TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED, /** * The first byte of data was not in the specified range for the packet type. * This range is 200-254 for lossy, and 160-191 for lossless packets. */ - TOX_ERR_SEND_CUSTOM_PACKET_INVALID, + TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID, /** * Attempted to send an empty packet. */ - TOX_ERR_SEND_CUSTOM_PACKET_EMPTY, + TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY, /** * Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE. */ - TOX_ERR_SEND_CUSTOM_PACKET_TOO_LONG, + TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG, /** * Send queue size exceeded. */ - TOX_ERR_SEND_CUSTOM_PACKET_SENDQ -} TOX_ERR_SEND_CUSTOM_PACKET; + TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ +} TOX_ERR_FRIEND_CUSTOM_PACKET; /** @@ -1845,8 +1845,8 @@ typedef enum TOX_ERR_SEND_CUSTOM_PACKET { * * @return true on success. */ -bool tox_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, - TOX_ERR_SEND_CUSTOM_PACKET *error); +bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_FRIEND_CUSTOM_PACKET *error); /** * The function type for the `friend_lossy_packet` callback. @@ -1880,8 +1880,8 @@ void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *func * * @return true on success. */ -bool tox_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, - TOX_ERR_SEND_CUSTOM_PACKET *error); +bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, + TOX_ERR_FRIEND_CUSTOM_PACKET *error); /** * The function type for the `friend_lossless_packet` callback. @@ -1919,7 +1919,7 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb * @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this * parameter is NULL, this function has no effect. */ -void tox_get_dht_id(const Tox *tox, uint8_t *dht_id); +void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id); typedef enum TOX_ERR_GET_PORT { @@ -1933,13 +1933,13 @@ typedef enum TOX_ERR_GET_PORT { /** * Return the UDP port this Tox instance is bound to. */ -uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error); /** * Return the TCP port this Tox instance is bound to. This is only relevant if * the instance is acting as a TCP relay. */ -uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); #include "tox_old.h" From 1eca7b8e678d8afd886dad7f44b7dc09597238f5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 12:18:52 -0400 Subject: [PATCH 053/101] Added simple status message test to tox_test.c --- auto_tests/tox_test.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 7cae9da6..7069c4b7 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -56,6 +56,16 @@ void print_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size ++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, uint32_t friendnumber, bool typing, void *userdata) @@ -376,6 +386,29 @@ START_TEST(test_few_clients) tox_friend_get_name(tox3, 0, temp_name, 0); ck_assert_msg(memcmp(temp_name, "Gentoo", sizeof("Gentoo")) == 0, "Name not correct"); + 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_iteration(tox1); + tox_iteration(tox2); + tox_iteration(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); @@ -460,6 +493,8 @@ START_TEST(test_few_clients) c_sleep(50); } + printf("Starting file transfer test.\n"); + file_accepted = file_size = file_recv = sendf_ok = size_recv = 0; long long unsigned int f_time = time(NULL); tox_callback_file_receive_chunk(tox3, write_file, &to_compare); From 4ee017078b1c8bbdf5f61b17194163768f3b0ad8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 12:19:59 -0400 Subject: [PATCH 054/101] tox_new() fixes. If data is NULL and length non zero, TOX_ERR_NEW_NULL is set. error is set to TOX_ERR_NEW_LOAD_BAD_FORMAT when load fails. --- toxcore/tox.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 554414b1..20f22e3c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -93,6 +93,11 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng if (!logger_get_global()) logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); + if (data == NULL && length != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL); + return NULL; + } + if (data) { if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED); @@ -160,14 +165,11 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng } if (messenger_load(m, data, length) == -1) { - /* TODO: uncomment this when tox is stable. - tox_kill(m); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); - return NULL; - */ + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); } - SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); return m; } From 7afab000f70c8a9d8070492fb42fb57bede4a75c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 13:03:14 -0400 Subject: [PATCH 055/101] tox_new now sets error to TOX_ERR_NEW_PORT_ALLOC when binding to port fails. --- auto_tests/messenger_test.c | 2 +- testing/Messenger_test.c | 2 +- toxcore/Messenger.c | 17 +++++++++++++++-- toxcore/Messenger.h | 11 ++++++++++- toxcore/network.c | 16 ++++++++++++++-- toxcore/network.h | 4 +++- toxcore/tox.c | 13 +++++++++---- 7 files changed, 53 insertions(+), 12 deletions(-) diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 8c71d6e7..2e1fe92a 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -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) diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 27216107..2e499f77 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -112,7 +112,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); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 546fe4a8..b0a3d12c 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1593,24 +1593,34 @@ static void LANdiscovery(Messenger *m) } /* Run this at startup. */ -Messenger *new_messenger(Messenger_Options *options) +Messenger *new_messenger(Messenger_Options *options, unsigned int *error) { Messenger *m = calloc(1, sizeof(Messenger)); + if (error) + *error = MESSENGER_ERROR_OTHER; + if ( ! m ) return NULL; + unsigned int net_err = 0; + if (options->udp_disabled) { /* this is the easiest way to completely disable UDP without changing too much code. */ m->net = calloc(1, sizeof(Networking_Core)); } else { IP ip; ip_init(&ip, options->ipv6enabled); - m->net = new_networking_ex(ip, options->port_range[0], options->port_range[1]); + m->net = new_networking_ex(ip, options->port_range[0], options->port_range[1], &net_err); } if (m->net == NULL) { free(m); + + if (error && net_err == 1) { + *error = MESSENGER_ERROR_PORT; + } + return NULL; } @@ -1654,6 +1664,9 @@ Messenger *new_messenger(Messenger_Options *options) set_nospam(&(m->fr), random_int()); set_filter_function(&(m->fr), &friend_already_added, m); + if (error) + *error = MESSENGER_ERROR_NONE; + return m; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index ae80760f..5de79c21 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -711,11 +711,20 @@ void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_ 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. diff --git a/toxcore/network.c b/toxcore/network.c index d7d07bdb..d974ddc2 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -471,7 +471,7 @@ static void at_shutdown(void) */ Networking_Core *new_networking(IP ip, uint16_t port) { - return new_networking_ex(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM)); + return new_networking_ex(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 0); } /* Initialize networking. @@ -481,8 +481,10 @@ Networking_Core *new_networking(IP ip, uint16_t port) * * 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_ex(IP ip, uint16_t port_from, uint16_t port_to) +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 @@ -501,6 +503,9 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t 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 @@ -643,6 +648,9 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) if (tries > 0) errno = 0; + if (error) + *error = 0; + return temp; } @@ -658,6 +666,10 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to) ip_ntoa(&ip), port_from, port_to); kill_networking(temp); + + if (error) + *error = 1; + return NULL; } diff --git a/toxcore/network.h b/toxcore/network.h index 0e7e5948..c67f523d 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -362,9 +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); +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); diff --git a/toxcore/tox.c b/toxcore/tox.c index 20f22e3c..cc507a65 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -154,13 +154,18 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng } } - Messenger *m = new_messenger(&m_options); - //TODO: TOX_ERR_NEW_MALLOC - //TODO: TOX_ERR_NEW_PORT_ALLOC + unsigned int m_error; + Messenger *m = new_messenger(&m_options, &m_error); if (!new_groupchats(m)) { kill_messenger(m); - SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); + + if (m_error == MESSENGER_ERROR_PORT) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC); + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); + } + return NULL; } From 28d707662b11c120e21697c3f1b208cdf7c6d0b2 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 13:11:28 -0400 Subject: [PATCH 056/101] Fixed tox_new issue. --- toxcore/tox.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index cc507a65..e99f7a75 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -99,6 +99,11 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng } if (data) { + if (length < TOX_ENC_SAVE_MAGIC_LENGTH) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); + return NULL; + } + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED); return NULL; @@ -169,7 +174,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng return NULL; } - if (messenger_load(m, data, length) == -1) { + if (data && length && messenger_load(m, data, length) == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); } else { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); From 8dc2db2025815ed6924c0fc4a7d83377e209f6f8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 15:17:34 -0400 Subject: [PATCH 057/101] Added position parameter to tox_file_send_chunk(). This is done so that the function now has the same parameters as the request chunk callback. --- auto_tests/tox_test.c | 13 +++++++++---- testing/nTox.c | 2 +- testing/tox_sync.c | 2 +- toxcore/Messenger.c | 8 +++++++- toxcore/Messenger.h | 4 +++- toxcore/tox.c | 10 +++++++--- toxcore/tox.h | 10 +++++++--- 7 files changed, 35 insertions(+), 14 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 7069c4b7..b5c0fd14 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -169,7 +169,7 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb uint8_t f_data[length]; memset(f_data, sending_num, length); - if (tox_file_send_chunk(tox, friend_number, file_number, f_data, length, &error)) { + if (tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error)) { ++sending_num; sending_pos += length; } else { @@ -296,9 +296,14 @@ END_TEST START_TEST(test_few_clients) { long long unsigned int con_time, cur_time = time(NULL); - Tox *tox1 = tox_new(0, 0, 0, 0); - Tox *tox2 = tox_new(0, 0, 0, 0); - Tox *tox3 = tox_new(0, 0, 0, 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"); { diff --git a/testing/nTox.c b/testing/nTox.c index 708397f9..de9c9db2 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -141,7 +141,7 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb 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, data, len, 0); + tox_file_send_chunk(tox, friend_number, file_number, position, data, len, 0); break; } } diff --git a/testing/tox_sync.c b/testing/tox_sync.c index bdbd2e3f..a41b464b 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -71,7 +71,7 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb 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, data, len, 0); + tox_file_send_chunk(tox, friend_number, file_number, position, data, len, 0); break; } } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b0a3d12c..03de5ea3 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1202,8 +1202,10 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, * return -4 if file transfer not transferring. * return -5 if trying to send too much data. * return -6 if packet queue full. + * return -7 if wrong position. */ -int file_data(const Messenger *m, int32_t friendnumber, uint32_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) { if (friend_not_valid(m, friendnumber)) return -1; @@ -1231,6 +1233,10 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, con } } + if (position != ft->transferred) { + return -7; + } + /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */ if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 5de79c21..edb16cff 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -637,8 +637,10 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, * return -4 if file transfer not transferring. * return -5 if trying to send too much data. * return -6 if packet queue full. + * return -7 if wrong position. */ -int file_data(const Messenger *m, int32_t friendnumber, uint32_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. * diff --git a/toxcore/tox.c b/toxcore/tox.c index e99f7a75..4f495977 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -932,11 +932,11 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uin return UINT32_MAX; } -bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, const uint8_t *data, size_t length, - TOX_ERR_FILE_SEND_CHUNK *error) +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, + size_t length, TOX_ERR_FILE_SEND_CHUNK *error) { Messenger *m = tox; - int ret = file_data(m, friend_number, file_number, data, length); + int ret = file_data(m, friend_number, file_number, position, data, length); if (ret == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK); @@ -967,6 +967,10 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, case -6: SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL); return 0; + + case -7: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION); + return 0; } /* can't happen */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 5323c4b6..868b7a1a 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1654,7 +1654,11 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { /** * Packet queue is full. */ - TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL + TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL, + /** + * Position parameter was wrong. + */ + TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION } TOX_ERR_FILE_SEND_CHUNK; /** @@ -1670,8 +1674,8 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * * @return true on success. */ -bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, const uint8_t *data, size_t length, - TOX_ERR_FILE_SEND_CHUNK *error); +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, + size_t length, TOX_ERR_FILE_SEND_CHUNK *error); /** From 7e5ca487b5ad1b3482c731d7b26e3e8bfee619f4 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 16:05:18 -0400 Subject: [PATCH 058/101] Don't assume tox_file_send_chunk() is called in the request chunk callback. --- toxcore/Messenger.c | 34 ++++++++++++++++++++++++++-------- toxcore/Messenger.h | 2 ++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 03de5ea3..b062dcc9 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1078,10 +1078,14 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (file_sendrequest(m, friendnumber, i, file_type, filesize, filename, filename_length) == 0) return -4; - m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NOT_ACCEPTED; - m->friendlist[friendnumber].file_sending[i].size = filesize; - m->friendlist[friendnumber].file_sending[i].transferred = 0; - m->friendlist[friendnumber].file_sending[i].paused = FILE_PAUSE_NOT; + struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->requested = 0; + ft->slots_allocated = 0; + ft->paused = FILE_PAUSE_NOT; + ++m->friendlist[friendnumber].num_sending_files; return i; @@ -1254,6 +1258,10 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin //TODO record packet ids to check if other received complete file. ft->transferred += length; + if (ft->slots_allocated) { + --ft->slots_allocated; + } + if (length == 0 || ft->size == ft->transferred) { ft->status = FILESTATUS_FINISHED; ft->last_packet_number = ret; @@ -1324,6 +1332,13 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) --m->friendlist[friendnumber].num_sending_files; } } + + /* TODO: if file is too slow, switch to the next. */ + if (ft->slots_allocated > free_slots) { + free_slots = 0; + } else { + free_slots -= ft->slots_allocated; + } } while (ft->status == FILESTATUS_TRANSFERRING && (ft->paused == FILE_PAUSE_NOT)) { @@ -1333,18 +1348,21 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) uint16_t length = MAX_CRYPTO_DATA_SIZE - 2; if (ft->size) { - if (ft->size == ft->transferred) { + if (ft->size == ft->requested) { break; } - if (ft->size - ft->transferred < length) { - length = ft->size - ft->transferred; + if (ft->size - ft->requested < length) { + length = ft->size - ft->requested; } } if (m->file_reqchunk) - (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, length, m->file_reqchunk_userdata); + (*m->file_reqchunk)(m, friendnumber, i, ft->requested, length, m->file_reqchunk_userdata); + ft->requested += length; + + ++ft->slots_allocated; --free_slots; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index edb16cff..0cbef76d 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -131,6 +131,8 @@ struct File_Transfers { 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. */ }; enum { FILESTATUS_NONE, From 0d67598aedda1ca144e9eddaf7cde6efe196df78 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 18:01:08 -0400 Subject: [PATCH 059/101] File transfer fixes and improvements. --- toxcore/Messenger.c | 14 ++++++++------ toxcore/net_crypto.c | 8 +++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b062dcc9..2914cf36 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1196,7 +1196,7 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, return 0; } -#define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 2) +#define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 4) /* Send file data. * * return 0 on success @@ -1309,10 +1309,11 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) int free_slots = crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)); - if (free_slots <= MIN_SLOTS_FREE) - return; - - free_slots -= MIN_SLOTS_FREE; + if (free_slots < MIN_SLOTS_FREE) { + free_slots = 0; + } else { + free_slots -= MIN_SLOTS_FREE; + } unsigned int i, num = m->friendlist[friendnumber].num_sending_files; @@ -1357,12 +1358,13 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) } } + ++ft->slots_allocated; + if (m->file_reqchunk) (*m->file_reqchunk)(m, friendnumber, i, ft->requested, length, m->file_reqchunk_userdata); ft->requested += length; - ++ft->slots_allocated; --free_slots; } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index bd5616a2..4be3a098 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -2586,7 +2586,13 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti if (conn == 0) return 0; - return conn->packets_left; + 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. From b4320e5fac5589692793013b8ab9a110e26fb704 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 18:56:33 -0400 Subject: [PATCH 060/101] File sending improvements. Use correct double to integer conversion. --- toxcore/net_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 4be3a098..0e700a41 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -2529,7 +2529,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) { From 334cb9c8db318516abd069a3cc2ec1fa233c8d9c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Mar 2015 19:04:49 -0400 Subject: [PATCH 061/101] Check more ports in tox_test.c --- auto_tests/tox_test.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index b5c0fd14..0b7f976b 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -312,6 +312,18 @@ START_TEST(test_few_clients) ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error"); } + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_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_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_connection_status(tox1, tox_connection_status, &to_compare); From 3bf259f69d408dc5c380383ee3c0cde0504e9f02 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 11 Mar 2015 17:26:25 -0500 Subject: [PATCH 062/101] Convert core code depending on the api --- auto_tests/tox_test.c | 106 +++++++++++++++++----------------- auto_tests/toxav_basic_test.c | 26 ++++----- auto_tests/toxav_many_test.c | 16 ++--- testing/irc_syncbot.c | 2 +- testing/nTox.c | 20 +++---- testing/tox_shell.c | 4 +- testing/tox_sync.c | 18 +++--- toxcore/tox.c | 10 ++-- toxcore/tox.h | 2 +- 9 files changed, 102 insertions(+), 102 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 7cae9da6..8df6316f 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -93,13 +93,13 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size 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, TOX_FILE_KIND kind, uint64_t filesize, +void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE 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) { + if (kind != TOX_FILE_TYPE_DATA) { ck_abort_msg("Bad kind"); return; } @@ -113,10 +113,10 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, TO TOX_ERR_FILE_CONTROL error; - if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) { + if (tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) { ++file_accepted; } else { - ck_abort_msg("tox_file_control failed. %i", error); + ck_abort_msg("tox_file_send_control failed. %i", error); } } @@ -221,7 +221,7 @@ START_TEST(test_one) { TOX_ERR_GET_PORT error; - ck_assert_msg(tox_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + 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"); } @@ -293,7 +293,7 @@ START_TEST(test_few_clients) { TOX_ERR_GET_PORT error; - ck_assert_msg(tox_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + 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"); } @@ -309,9 +309,9 @@ START_TEST(test_few_clients) uint8_t off = 1; while (1) { - tox_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (tox_get_connection_status(tox1) && tox_get_connection_status(tox2) && tox_get_connection_status(tox3)) { if (off) { @@ -334,17 +334,17 @@ START_TEST(test_few_clients) tox_callback_friend_message(tox3, print_message, &to_compare); uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1]; memset(msgs, 'G', sizeof(msgs)); - TOX_ERR_SEND_MESSAGE errm; - tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm); - ck_assert_msg(errm == TOX_ERR_SEND_MESSAGE_TOO_LONG, "TOX_MAX_MESSAGE_LENGTH is too small\n"); - tox_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); - ck_assert_msg(errm == TOX_ERR_SEND_MESSAGE_OK, "TOX_MAX_MESSAGE_LENGTH is too big\n"); + TOX_ERR_FRIEND_SEND_MESSAGE errm; + tox_friend_send_message(tox2, 0, 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, 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_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (messages_received) break; @@ -361,9 +361,9 @@ START_TEST(test_few_clients) while (1) { name_changes = 0; - tox_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (name_changes) break; @@ -381,9 +381,9 @@ START_TEST(test_few_clients) while (1) { typing_changes = 0; - tox_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (typing_changes == 2) @@ -399,9 +399,9 @@ START_TEST(test_few_clients) while (1) { typing_changes = 0; - tox_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (typing_changes == 1) break; @@ -419,16 +419,16 @@ START_TEST(test_few_clients) 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)); - int ret = tox_send_lossless_packet(tox2, 0, data_c, sizeof(data_c), 0); - ck_assert_msg(ret == 0, "tox_send_lossless_packet bigger fail %i", ret); - ret = tox_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0); - ck_assert_msg(ret == 1, "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_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (custom_packet == 1) break; @@ -441,16 +441,16 @@ START_TEST(test_few_clients) packet_number = 200; 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), 0); - ck_assert_msg(ret == 0, "tox_send_lossy_packet bigger fail %i", ret); - ret = tox_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0); - ck_assert_msg(ret == 1, "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_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + tox_iterate(tox1); + tox_iterate(tox2); + tox_iterate(tox3); if (custom_packet == 1) break; @@ -463,20 +463,20 @@ START_TEST(test_few_clients) file_accepted = file_size = file_recv = sendf_ok = size_recv = 0; long long unsigned int f_time = time(NULL); tox_callback_file_receive_chunk(tox3, write_file, &to_compare); - tox_callback_file_control(tox2, file_print_control, &to_compare); + tox_callback_file_recv_control(tox2, file_print_control, &to_compare); tox_callback_file_request_chunk(tox2, tox_file_request_chunk, &to_compare); - tox_callback_file_control(tox3, file_print_control, &to_compare); + tox_callback_file_recv_control(tox3, file_print_control, &to_compare); tox_callback_file_receive(tox3, tox_file_receive, &to_compare); uint64_t totalf_size = 100 * 1024 * 1024; - uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), + uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_TYPE_DATA, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), 0); ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail"); while (1) { - tox_iteration(tox1); - tox_iteration(tox2); - tox_iteration(tox3); + 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) { @@ -526,7 +526,7 @@ START_TEST(test_many_clients) { TOX_ERR_GET_PORT error; - ck_assert_msg(tox_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + 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"); } @@ -573,7 +573,7 @@ loop_top: } for (i = 0; i < NUM_TOXES; ++i) { - tox_iteration(toxes[i]); + tox_iterate(toxes[i]); } c_sleep(50); @@ -654,7 +654,7 @@ START_TEST(test_many_group) { TOX_ERR_GET_PORT error; - ck_assert_msg(tox_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + 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"); } @@ -678,7 +678,7 @@ START_TEST(test_many_group) break; for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_iteration(toxes[i]); + tox_iterate(toxes[i]); } c_sleep(50); @@ -696,7 +696,7 @@ START_TEST(test_many_group) while (1) { for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_iteration(toxes[i]); + tox_iterate(toxes[i]); } if (!invite_counter) { @@ -734,7 +734,7 @@ START_TEST(test_many_group) for (j = 0; j < 20; ++j) { for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_iteration(toxes[i]); + tox_iterate(toxes[i]); } c_sleep(50); @@ -747,7 +747,7 @@ START_TEST(test_many_group) for (j = 0; j < 10; ++j) { for (i = 0; i < NUM_GROUP_TOX; ++i) { - tox_iteration(toxes[i]); + tox_iterate(toxes[i]); } c_sleep(50); diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index 59730edf..3f4a3b8d 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -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_iteration(bootstrap_node); tox_iteration(Alice); tox_iteration(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");\ @@ -267,9 +267,9 @@ START_TEST(test_AV_flows) uint8_t off = 1; while (1) { - tox_iteration(bootstrap_node); - tox_iteration(Alice); - tox_iteration(Bob); + tox_iterate(bootstrap_node); + tox_iterate(Alice); + tox_iterate(Bob); if (tox_get_connection_status(bootstrap_node) && tox_get_connection_status(Alice) && tox_get_connection_status(Bob) && off) { @@ -484,9 +484,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_iteration(bootstrap_node); - tox_iteration(Alice); - tox_iteration(Bob); + tox_iterate(bootstrap_node); + tox_iterate(Alice); + tox_iterate(Bob); switch ( step ) { case 0: /* Alice */ @@ -525,9 +525,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_iteration(bootstrap_node); - tox_iteration(Alice); - tox_iteration(Bob); + tox_iterate(bootstrap_node); + tox_iterate(Alice); + tox_iterate(Bob); toxav_do(status_control.Alice.av); toxav_do(status_control.Bob.av); @@ -570,9 +570,9 @@ START_TEST(test_AV_flows) int running = 1; while (running) { - tox_iteration(bootstrap_node); - tox_iteration(Alice); - tox_iteration(Bob); + tox_iterate(bootstrap_node); + tox_iterate(Alice); + tox_iterate(Bob); toxav_do(status_control.Alice.av); toxav_do(status_control.Bob.av); diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index 4002c4e7..f22043e1 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -294,11 +294,11 @@ START_TEST(test_AV_three_calls) uint8_t off = 1; while (1) { - tox_iteration(bootstrap_node); - tox_iteration(caller); + tox_iterate(bootstrap_node); + tox_iterate(caller); for (i = 0; i < 3; i ++) { - tox_iteration(callees[i]); + tox_iterate(callees[i]); } @@ -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_iteration(bootstrap_node); - tox_iteration(caller); - tox_iteration(callees[0]); - tox_iteration(callees[1]); - tox_iteration(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); diff --git a/testing/irc_syncbot.c b/testing/irc_syncbot.c index df9e964c..ee49e160 100644 --- a/testing/irc_syncbot.c +++ b/testing/irc_syncbot.c @@ -342,7 +342,7 @@ int main(int argc, char *argv[]) } } - tox_iteration(tox); + tox_iterate(tox); usleep(1000 * 50); } diff --git a/testing/nTox.c b/testing/nTox.c index 708397f9..d373c683 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -158,7 +158,7 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, + uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_TYPE_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, 0); if (filenum == -1) @@ -389,13 +389,13 @@ void line_eval(Tox *m, char *line) new_lines(numstring); } else if (inpt_command == 'd') { - tox_iteration(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), NULL) < 1) { + if (tox_friend_send_message(m, num, (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); @@ -607,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), NULL); + uint32_t res = tox_friend_send_message(m, friendnumber, (uint8_t *)line, strlen(line), NULL); if (res == 0) { char sss[128]; @@ -1127,12 +1127,12 @@ void print_groupnamelistchange(Tox *m, int groupnumber, int peernumber, uint8_t print_groupchatpeers(m, groupnumber); } } -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, +void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE type, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) { - if (type != TOX_FILE_KIND_DATA) { + if (type != TOX_FILE_TYPE_DATA) { new_lines("Refused invalid file type."); - tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -1140,7 +1140,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, 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_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { + if (tox_file_send_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 @@ -1270,7 +1270,7 @@ int main(int argc, char *argv[]) tox_callback_group_invite(m, print_invite, NULL); tox_callback_group_message(m, print_groupmessage, NULL); tox_callback_file_receive_chunk(m, write_file, NULL); - tox_callback_file_control(m, file_print_control, NULL); + tox_callback_file_recv_control(m, file_print_control, NULL); tox_callback_file_receive(m, file_request_accept, NULL); tox_callback_file_request_chunk(m, tox_file_request_chunk, NULL); tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL); @@ -1326,7 +1326,7 @@ int main(int argc, char *argv[]) } } - tox_iteration(m); + tox_iterate(m); do_refresh(); int c = timeout_getch(m); diff --git a/testing/tox_shell.c b/testing/tox_shell.c index c8dc9ff2..38fe6364 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -148,10 +148,10 @@ int main(int argc, char *argv[]) if (ret <= 0) break; - tox_send_message(tox, num, buf, ret, 0); + tox_friend_send_message(tox, num, buf, ret, 0); } - tox_iteration(tox); + tox_iterate(tox); c_sleep(1); } diff --git a/testing/tox_sync.c b/testing/tox_sync.c index bdbd2e3f..61f390fc 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -88,7 +88,7 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, + uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_TYPE_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, 0); if (filenum == -1) @@ -124,12 +124,12 @@ int not_sending() static char path[1024]; -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, +void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE type, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) { - if (type != TOX_FILE_KIND_DATA) { + if (type != TOX_FILE_TYPE_DATA) { printf("Refused invalid file type."); - tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -151,7 +151,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, if (tempfile != 0) { fclose(tempfile); - tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -159,11 +159,11 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, file_recv[file_index].file = fopen(fullpath, "wb"); if (file_recv[file_index].file == 0) { - tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } - if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { + if (tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { printf("Accepted file transfer. (file: %s)\n", fullpath); } @@ -231,7 +231,7 @@ int main(int argc, char *argv[]) Tox *tox = tox_new(0, 0, 0, 0); tox_callback_file_receive_chunk(tox, write_file, NULL); - tox_callback_file_control(tox, file_print_control, NULL); + tox_callback_file_recv_control(tox, file_print_control, NULL); tox_callback_file_receive(tox, file_request_accept, NULL); tox_callback_file_request_chunk(tox, tox_file_request_chunk, NULL); tox_callback_friend_connection_status(tox, print_online, NULL); @@ -306,7 +306,7 @@ int main(int argc, char *argv[]) } } - tox_iteration(tox); + tox_iterate(tox); c_sleep(1); } diff --git a/toxcore/tox.c b/toxcore/tox.c index 9a821bfb..6340aee9 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -302,7 +302,7 @@ uint32_t tox_iteration_interval(const Tox *tox) return messenger_run_interval(m); } -void tox_iteration(Tox *tox) +void tox_iterate(Tox *tox) { Messenger *m = tox; do_messenger(m); @@ -822,7 +822,7 @@ bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) return 1; } -bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, +bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, TOX_ERR_FILE_CONTROL *error) { Messenger *m = tox; @@ -1077,7 +1077,7 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb custom_lossless_packet_registerhandler(m, function, user_data); } -void tox_get_dht_id(const Tox *tox, uint8_t *dht_id) +void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id) { if (dht_id) { const Messenger *m = tox; @@ -1085,7 +1085,7 @@ void tox_get_dht_id(const Tox *tox, uint8_t *dht_id) } } -uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) +uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) { const Messenger *m = tox; uint16_t port = htons(m->net->port); @@ -1099,7 +1099,7 @@ uint16_t tox_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) return port; } -uint16_t tox_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) +uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) { /* TCP server not yet implemented in clients. */ SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); diff --git a/toxcore/tox.h b/toxcore/tox.h index c4309e59..96969c43 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -652,7 +652,7 @@ uint32_t tox_iteration_interval(const Tox *tox); * The main loop that needs to be run in intervals of tox_iteration_interval() * milliseconds. */ -void tox_do_iteration(Tox *tox); +void tox_iterate(Tox *tox); /******************************************************************************* From eec1042695378c8e7fa2dc02970c79b9caddcf3d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 08:36:07 -0400 Subject: [PATCH 063/101] tox_friend_get_public_key() now does nothing when public_key is NULL. --- toxcore/tox.c | 1 - toxcore/tox.h | 1 - 2 files changed, 2 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 4f495977..c527ce96 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -546,7 +546,6 @@ bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t * TOX_ERR_FRIEND_GET_PUBLIC_KEY *error) { if (!public_key) { - SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL); return 0; } diff --git a/toxcore/tox.h b/toxcore/tox.h index 868b7a1a..d23065ff 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -948,7 +948,6 @@ uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, - TOX_ERR_FRIEND_GET_PUBLIC_KEY_NULL, /** * No friend with the given number exists on the friend list. */ From 669975c226a385c1d0ffee8384abd776c7962d53 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 12:40:21 -0400 Subject: [PATCH 064/101] tox_file_send_chunk() must now send data the same length as requested in the requested chunk callback. For zero size transfers if the data sent is not the same length, the file is assumed to be done. --- toxcore/Messenger.c | 44 ++++++++++++++++++++++++++++++++------------ toxcore/Messenger.h | 2 +- toxcore/tox.c | 2 +- toxcore/tox.h | 23 ++++++++++------------- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 2914cf36..607630b6 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1196,6 +1196,28 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, return 0; } +/* return packet number on success. + * return -1 on failure. + */ +static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, + uint16_t length) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + uint8_t packet[2 + length]; + packet[0] = PACKET_ID_FILE_DATA; + packet[1] = filenumber; + + if (length) { + memcpy(packet + 2, data, length); + } + + return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), packet, sizeof(packet), 1); +} + +#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2) #define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 4) /* Send file data. * @@ -1204,7 +1226,7 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, * return -2 if friend not online. * return -3 if filenumber invalid. * return -4 if file transfer not transferring. - * return -5 if trying to send too much data. + * return -5 if bad data size. * return -6 if packet queue full. * return -7 if wrong position. */ @@ -1228,13 +1250,17 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin if (ft->paused != FILE_PAUSE_NOT) return -4; - if (length > MAX_CRYPTO_DATA_SIZE - 2) + if (length > MAX_FILE_DATA_SIZE) return -5; if (ft->size) { if (ft->size - ft->transferred < length) { return -5; } + + if (length != MAX_FILE_DATA_SIZE && (ft->transferred + length) != ft->size) { + return -5; + } } if (position != ft->transferred) { @@ -1246,13 +1272,7 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) return -6; - uint8_t packet[2 + length]; - packet[0] = PACKET_ID_FILE_DATA; - packet[1] = filenumber; - memcpy(packet + 2, data, length); - - int64_t ret = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, - m->friendlist[friendnumber].friendcon_id), packet, sizeof(packet), 1); + int64_t ret = send_file_data_packet(m, friendnumber, filenumber, data, length); if (ret != -1) { //TODO record packet ids to check if other received complete file. @@ -1262,7 +1282,7 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin --ft->slots_allocated; } - if (length == 0 || ft->size == ft->transferred) { + if (length != MAX_FILE_DATA_SIZE || ft->size == ft->transferred) { ft->status = FILESTATUS_FINISHED; ft->last_packet_number = ret; } @@ -1346,7 +1366,7 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) if (free_slots == 0) break; - uint16_t length = MAX_CRYPTO_DATA_SIZE - 2; + uint16_t length = MAX_FILE_DATA_SIZE; if (ft->size) { if (ft->size == ft->requested) { @@ -1980,7 +2000,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) ft->transferred += file_data_length; - if (ft->size && ft->transferred >= ft->size) { + if ((ft->size && ft->transferred >= ft->size) || file_data_length != MAX_FILE_DATA_SIZE) { file_data_length = 0; file_data = NULL; position = ft->transferred; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 0cbef76d..5dec83df 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -637,7 +637,7 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, * return -2 if friend not online. * return -3 if filenumber invalid. * return -4 if file transfer not transferring. - * return -5 if trying to send too much data. + * return -5 if bad data size. * return -6 if packet queue full. * return -7 if wrong position. */ diff --git a/toxcore/tox.c b/toxcore/tox.c index c527ce96..5dfac2c8 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -960,7 +960,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, return 0; case -5: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH); return 0; case -6: diff --git a/toxcore/tox.h b/toxcore/tox.h index d23065ff..eb6b4f31 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1645,11 +1645,11 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { */ TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING, /** - * Attempted to send more data than requested. The requested data size is + * Attempted to send more or less data than requested. The requested data size is * adjusted according to maximum transmission unit and the expected end of - * the file. Trying to send more will result in no data being sent. + * the file. Trying to send less or more than requested will return this error. */ - TOX_ERR_FILE_SEND_CHUNK_TOO_LARGE, + TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH, /** * Packet queue is full. */ @@ -1664,12 +1664,12 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * Send a chunk of file data to a friend. * * This function is called in response to the `file_request_chunk` callback. The - * length parameter should be equal to or less than the one received though the - * callback. If it is zero, the transfer is assumed complete. For files with - * known size, Core will know that the transfer is complete after the last byte - * has been received, so it is not necessary (though not harmful) to send a - * zero-length chunk to terminate. For streams, it is necessary for the last - * chunk sent to be zero-length. + * length parameter should be equal to the one received though the callback. + * If it is zero, the transfer is assumed complete. For files with known size, + * Core will know that the transfer is complete after the last byte has been + * received, so it is not necessary (though not harmful) to send a zero-length + * chunk to terminate. For streams, core will know that the transfer is finished + * if a chunk with length less than the length requested in the callback is sent. * * @return true on success. */ @@ -1694,10 +1694,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, * In response to receiving this callback, the client should call the function * `tox_file_send_chunk` with the requested chunk. If the number of bytes sent * through that function is zero, the file transfer is assumed complete. A - * client may choose to send less than requested, if it is reading from a - * stream that doesn't have more data, yet, and it still wants to send some - * data to the other side. However, this will generally be less efficient than - * waiting for a full chunk size of data to be ready. + * client must send the full length of data requested with this callback. * * @param friend_number The friend number of the receiving friend for this file. * @param file_number The file transfer identifier returned by tox_file_send. From 96d9cef66c551feae380596d77e6f120525ad0ca Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 13:00:35 -0400 Subject: [PATCH 065/101] File kind is now a uint32_t. This allows clients to agree on what numbers mean what without having it be set in core. --- toxcore/Messenger.c | 4 ++-- toxcore/Messenger.h | 6 +++--- toxcore/tox.c | 4 ++-- toxcore/tox.h | 16 ++++++++-------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 607630b6..f61050bc 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -976,9 +976,9 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin /* Set the callback for file send requests. * - * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int filetype, uint64_t filesize, uint8_t *filename, size_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, uint32_t, uint32_t, unsigned int, uint64_t, +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) { m->file_sendrequest = function; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 5dec83df..d4cfa431 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -255,7 +255,7 @@ struct Messenger { 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, uint32_t, uint32_t, unsigned int, uint64_t, const uint8_t *, size_t, + 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, uint32_t, uint32_t, unsigned int, void *); @@ -574,9 +574,9 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin /* Set the callback for file send requests. * - * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int filetype, uint64_t filesize, uint8_t *filename, size_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, uint32_t, uint32_t, unsigned int, uint64_t, +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); diff --git a/toxcore/tox.c b/toxcore/tox.c index 5dfac2c8..a8a44af3 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -888,8 +888,8 @@ void tox_callback_file_control(Tox *tox, tox_file_control_cb *function, void *us callback_file_control(m, function, user_data); } -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, - const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, + size_t filename_length, TOX_ERR_FILE_SEND *error) { if (!filename) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); diff --git a/toxcore/tox.h b/toxcore/tox.h index eb6b4f31..4fc139b1 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1617,8 +1617,8 @@ typedef enum TOX_ERR_FILE_SEND { * number is per friend. File numbers are reused after a transfer terminates. * on failure, this function returns UINT32_MAX. */ -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, - const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, + size_t filename_length, TOX_ERR_FILE_SEND *error); typedef enum TOX_ERR_FILE_SEND_CHUNK { @@ -1664,11 +1664,11 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * Send a chunk of file data to a friend. * * This function is called in response to the `file_request_chunk` callback. The - * length parameter should be equal to the one received though the callback. - * If it is zero, the transfer is assumed complete. For files with known size, - * Core will know that the transfer is complete after the last byte has been - * received, so it is not necessary (though not harmful) to send a zero-length - * chunk to terminate. For streams, core will know that the transfer is finished + * length parameter should be equal to the one received though the callback. + * If it is zero, the transfer is assumed complete. For files with known size, + * Core will know that the transfer is complete after the last byte has been + * received, so it is not necessary (though not harmful) to send a zero-length + * chunk to terminate. For streams, core will know that the transfer is finished * if a chunk with length less than the length requested in the callback is sent. * * @return true on success. @@ -1731,7 +1731,7 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi * @param file_number The friend-specific file number the data received is * associated with. */ -typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, +typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); /** From 64fefb6f43e9213db9f3313aa7e8af7c36bf8538 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 13 Mar 2015 12:34:14 -0500 Subject: [PATCH 066/101] revert to TOX_FILE_KIND --- auto_tests/tox_test.c | 6 +++--- testing/nTox.c | 6 +++--- testing/tox_sync.c | 6 +++--- toxcore/tox.c | 2 +- toxcore/tox.h | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 8df6316f..938c4499 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -93,13 +93,13 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size 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, TOX_FILE_TYPE kind, uint64_t filesize, +void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, uint64_t filesize, const uint8_t *filename, size_t filename_length, void *userdata) { if (*((uint32_t *)userdata) != 974536) return; - if (kind != TOX_FILE_TYPE_DATA) { + if (kind != TOX_FILE_KIND_DATA) { ck_abort_msg("Bad kind"); return; } @@ -468,7 +468,7 @@ START_TEST(test_few_clients) tox_callback_file_recv_control(tox3, file_print_control, &to_compare); tox_callback_file_receive(tox3, tox_file_receive, &to_compare); uint64_t totalf_size = 100 * 1024 * 1024; - uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_TYPE_DATA, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), + uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), 0); ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail"); diff --git a/testing/nTox.c b/testing/nTox.c index d373c683..d6adecaa 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -158,7 +158,7 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_TYPE_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, + uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, 0); if (filenum == -1) @@ -1127,10 +1127,10 @@ void print_groupnamelistchange(Tox *m, int groupnumber, int peernumber, uint8_t print_groupchatpeers(m, groupnumber); } } -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE type, +void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) { - if (type != TOX_FILE_TYPE_DATA) { + if (type != TOX_FILE_KIND_DATA) { new_lines("Refused invalid file type."); tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 61f390fc..520d6629 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -88,7 +88,7 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_TYPE_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, + uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, 0); if (filenum == -1) @@ -124,10 +124,10 @@ int not_sending() static char path[1024]; -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE type, +void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) { - if (type != TOX_FILE_TYPE_DATA) { + if (type != TOX_FILE_KIND_DATA) { printf("Refused invalid file type."); tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; diff --git a/toxcore/tox.c b/toxcore/tox.c index 6340aee9..0b702a1b 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -877,7 +877,7 @@ void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function callback_file_control(m, function, user_data); } -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_TYPE kind, uint64_t file_size, +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) { if (!filename) { diff --git a/toxcore/tox.h b/toxcore/tox.h index 96969c43..7093a232 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1390,12 +1390,12 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * ******************************************************************************/ -typedef enum TOX_FILE_TYPE { +typedef enum TOX_FILE_KIND { /** * Arbitrary file data. Clients can choose to handle it based on the file name * or magic or any other way they choose. */ - TOX_FILE_TYPE_DATA, + TOX_FILE_KIND_DATA, /** * Avatar data. This consists of tox_hash(image) + image. * @@ -1412,8 +1412,8 @@ typedef enum TOX_FILE_TYPE { * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar * transfer if it matches. */ - TOX_FILE_TYPE_AVATAR -} TOX_FILE_TYPE; + TOX_FILE_KIND_AVATAR +} TOX_FILE_KIND; /** @@ -1618,7 +1618,7 @@ typedef enum TOX_ERR_FILE_SEND { * number is per friend. File numbers are reused after a transfer terminates. * on failure, this function returns UINT32_MAX. */ -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_TYPE kind, uint64_t file_size, +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, TOX_FILE_KIND kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); @@ -1731,7 +1731,7 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi * @param file_number The friend-specific file number the data received is * associated with. */ -typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_TYPE kind, +typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); /** From c3e07b73d3cd824ffc5a5ea681cde0c7c8c7732e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 15:38:44 -0400 Subject: [PATCH 067/101] Remove TOX_FILE_KIND typedef. --- testing/nTox.c | 4 ++-- testing/tox_sync.c | 4 ++-- toxcore/tox.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index e566c79f..df76cdc5 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1127,8 +1127,8 @@ void print_groupnamelistchange(Tox *m, int groupnumber, int peernumber, uint8_t print_groupchatpeers(m, groupnumber); } } -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, - uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) +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."); diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 78c31244..603c6f22 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -124,8 +124,8 @@ int not_sending() static char path[1024]; -void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_KIND type, - uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data) +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."); diff --git a/toxcore/tox.h b/toxcore/tox.h index 993a1dad..82552eea 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1389,7 +1389,7 @@ void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void * ******************************************************************************/ -typedef enum TOX_FILE_KIND { +enum TOX_FILE_KIND { /** * Arbitrary file data. Clients can choose to handle it based on the file name * or magic or any other way they choose. @@ -1412,7 +1412,7 @@ typedef enum TOX_FILE_KIND { * transfer if it matches. */ TOX_FILE_KIND_AVATAR -} TOX_FILE_KIND; +}; /** From 29857a3da4169d4aed7dd75a961a1936be86adab Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 16:33:55 -0400 Subject: [PATCH 068/101] This belongs in the previous commit. --- auto_tests/tox_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 0303c128..467fa7cb 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -103,7 +103,7 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size 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, TOX_FILE_KIND kind, uint64_t filesize, +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) From 11e8e8bd3a8dfc6f94ccecda5b1b98848b09e9ec Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Mar 2015 16:51:41 -0400 Subject: [PATCH 069/101] When link can't send packets anymore, stop the request chunk callback. Removed time variable in packet struct and replaced it with sent variable. --- toxcore/Messenger.c | 5 +++ toxcore/net_crypto.c | 88 +++++++++++++++++++++++++++----------------- toxcore/net_crypto.h | 7 +++- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f61050bc..83aaf19b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1386,6 +1386,11 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) ft->requested += length; --free_slots; + + if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id))) { + free_slots = 0; + } } if (num == 0) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 0e700a41..50f4d8c1 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -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) { - return -1; - } else { - send_failed = 1; - } - } else { - dt->time = temp_time; - } - } - } - - if (!send_failed) { - conn->maximum_speed_reached = 0; - } + if (conn->maximum_speed_reached && congestion_control) { + return -1; } 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); @@ -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. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 7e59475e..ca79586f 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -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. From a1127e63d5f630720be6cf6ecef9d799e94f319f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Mar 2015 10:03:19 -0400 Subject: [PATCH 070/101] Better DHT distance function. --- toxcore/DHT.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 2d3d6ffe..9ebe11cf 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -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; From 6cf727063859efd6093ac1b4300735746ccd9992 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Mar 2015 10:05:39 -0400 Subject: [PATCH 071/101] Make nTox save on exit. --- testing/nTox.c | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/nTox.c b/testing/nTox.c index df76cdc5..d60d57f4 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1347,6 +1347,7 @@ int main(int argc, char *argv[]) } free(binary_string); + save_data_file(m, filename); tox_kill(m); endwin(); return 0; From fab2daf57a1f368c7f4286dfdb908314dc2076bc Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Mar 2015 10:54:42 -0400 Subject: [PATCH 072/101] Install tox_old.h too. --- toxcore/Makefile.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 9fd1f94a..9afe7791 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -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 From 518a399eb0cb0ffdc6798ab7bab1d4b1c973ef2e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Mar 2015 13:35:50 -0400 Subject: [PATCH 073/101] There are many scenarios where the user would want to modify the contents pointed by proxy_address. --- toxcore/tox.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index 82552eea..286d323a 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -344,7 +344,7 @@ struct Tox_Options { * * This member is ignored (it can be NULL) if proxy_enabled is false. */ - const char *proxy_address; + char *proxy_address; /** * The port to use to connect to the proxy server. From 409897f7aeb9d3c710aed4466f75eb058842a343 Mon Sep 17 00:00:00 2001 From: Impyy Date: Sun, 15 Mar 2015 12:47:59 +0100 Subject: [PATCH 074/101] Initialize Tox_Options with default values in tox_options_new --- toxcore/tox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toxcore/tox.c b/toxcore/tox.c index 5493d1d5..6861ca4f 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -75,6 +75,8 @@ struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error) struct Tox_Options *options = calloc(sizeof(struct Tox_Options), 1); if (options) { + tox_options_default(options); + SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK); return options; } From ec659491b265db747e67ef8a166d224c0453397d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 15 Mar 2015 18:35:22 -0400 Subject: [PATCH 075/101] Avatar hash is now the filename of the file transfer instead of the first 32 bytes. Enforce length of filename in core when transfer is an avatar type transfer to make things more safe. --- toxcore/Messenger.c | 18 +++++++++++++----- toxcore/Messenger.h | 8 +++++++- toxcore/tox.c | 2 +- toxcore/tox.h | 12 +++++++----- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 83aaf19b..911c92da 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1051,7 +1051,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi * Maximum filename length is 255 bytes. * return file number on success * return -1 if friend not found. - * return -2 if filename too big. + * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). * @@ -1065,6 +1065,9 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (filename_length > MAX_FILENAME_LENGTH) return -2; + if (file_type == FILEKIND_AVATAR && filename_length != crypto_hash_sha256_BYTES) + return -2; + uint32_t i; for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { @@ -1937,9 +1940,14 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) uint8_t filenumber = data[0]; uint64_t filesize; uint32_t file_type; + uint16_t filename_length = data_length - head_length; memcpy(&file_type, data + 1, sizeof(file_type)); file_type = ntohl(file_type); + /* Check if the name is the right size if file is avatar. */ + if (file_type == FILEKIND_AVATAR && filename_length != crypto_hash_sha256_BYTES) + break; + memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); net_to_host((uint8_t *) &filesize, sizeof(filesize)); m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; @@ -1948,16 +1956,16 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) m->friendlist[i].file_receiving[filenumber].paused = FILE_PAUSE_NOT; /* Force NULL terminate file name. */ - uint8_t filename_terminated[data_length - head_length + 1]; - memcpy(filename_terminated, data + head_length, data_length - head_length); - filename_terminated[data_length - head_length] = 0; + uint8_t filename_terminated[filename_length + 1]; + memcpy(filename_terminated, data + head_length, filename_length); + filename_terminated[filename_length] = 0; uint32_t real_filenumber = filenumber; real_filenumber += 1; real_filenumber <<= 16; if (m->file_sendrequest) - (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename_terminated, data_length - head_length, + (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename_terminated, filename_length, m->file_sendrequest_userdata); break; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index d4cfa431..716ac851 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -159,6 +159,12 @@ enum { FILECONTROL_RESUME_BROKEN }; +enum { + FILEKIND_DATA, + FILEKIND_AVATAR +}; + + typedef struct Messenger Messenger; typedef struct { @@ -608,7 +614,7 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_ * Maximum filename length is 255 bytes. * return file number on success * return -1 if friend not found. - * return -2 if filename too big. + * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). * diff --git a/toxcore/tox.c b/toxcore/tox.c index 5493d1d5..51aa85ad 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -915,7 +915,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t return UINT32_MAX; case -2: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH); return UINT32_MAX; case -3: diff --git a/toxcore/tox.h b/toxcore/tox.h index 286d323a..1457a70b 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1396,7 +1396,8 @@ enum TOX_FILE_KIND { */ TOX_FILE_KIND_DATA, /** - * Avatar data. This consists of tox_hash(image) + image. + * Avatar filename. This consists of tox_hash(image). + * Avatar data. This consists of the image data. * * Avatars can be sent at any time the client wishes. Generally, a client will * send the avatar to a friend when that friend comes online, and to all @@ -1406,8 +1407,8 @@ enum TOX_FILE_KIND { * * Clients who receive avatar send requests can reject it (by sending * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by - * sending TOX_FILE_CONTROL_RESUME). The first chunk will contain the hash in - * its first TOX_HASH_LENGTH bytes. A client can compare this hash with a + * sending TOX_FILE_CONTROL_RESUME). The filename of length TOX_HASH_LENGTH bytes + * will contain the hash. A client can compare this hash with a * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar * transfer if it matches. */ @@ -1551,9 +1552,10 @@ typedef enum TOX_ERR_FILE_SEND { */ TOX_ERR_FILE_SEND_NAME_EMPTY, /** - * Filename length exceeded 255 bytes. + * Filename length exceeded 255 bytes or if kind was equal to TOX_FILE_KIND_AVATAR + * the length was not TOX_HASH_LENGTH. */ - TOX_ERR_FILE_SEND_NAME_TOO_LONG, + TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH, /** * Too many ongoing transfers. The maximum number of concurrent file transfers * is 256 per friend per direction (sending and receiving). From fa7c21f95c78eabf3c0f0d247cd7f28ec47eff3d Mon Sep 17 00:00:00 2001 From: iphydf Date: Mon, 16 Mar 2015 02:25:06 +0000 Subject: [PATCH 076/101] New API fixups. --- auto_tests/tox_test.c | 2 +- toxcore/tox.c | 22 +++++++++++----------- toxcore/tox.h | 43 ++++++++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 467fa7cb..dc23040d 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -615,7 +615,7 @@ loop_top: uint16_t counter = 0; for (i = 0; i < NUM_TOXES; ++i) { - for (j = 0; j < tox_friend_list_size(toxes[i]); ++j) + 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; } diff --git a/toxcore/tox.c b/toxcore/tox.c index 54daafc8..da109502 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -135,7 +135,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng break; default: - SET_ERROR_PARAMETER(error, TOX_ERR_PROXY_TYPE); + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE); return NULL; } @@ -150,7 +150,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng if (m_options.ipv6enabled) m_options.proxy_info.ip_port.ip.family = AF_UNSPEC; - if (!addr_resolve_or_parse_ip(options->proxy_address, &m_options.proxy_info.ip_port.ip, NULL)) { + if (!addr_resolve_or_parse_ip(options->proxy_host, &m_options.proxy_info.ip_port.ip, NULL)) { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST); //TODO: TOX_ERR_NEW_PROXY_NOT_FOUND if domain. return NULL; @@ -249,7 +249,7 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t * return ret; } else { /* DHT only works on UDP. */ if (DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key) == 0) { - SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_ADDRESS); + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); return 0; } @@ -275,7 +275,7 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8 } if (address_to_ip(m, address, &ip_port, &ip_port_v4) == -1) { - SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_ADDRESS); + SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); return 0; } @@ -350,12 +350,12 @@ void tox_self_get_public_key(const Tox *tox, uint8_t *public_key) memcpy(public_key, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); } -void tox_self_get_private_key(const Tox *tox, uint8_t *private_key) +void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key) { const Messenger *m = tox; - if (private_key) - memcpy(private_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); + if (secret_key) + memcpy(secret_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); } bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error) @@ -567,18 +567,18 @@ bool tox_friend_exists(const Tox *tox, uint32_t friend_number) return m_friend_exists(m, friend_number); } -size_t tox_friend_list_size(const Tox *tox) +size_t tox_self_get_friend_list_size(const Tox *tox) { const Messenger *m = tox; return count_friendlist(m); } -void tox_friend_get_list(const Tox *tox, uint32_t *list) +void tox_self_get_friend_list(const Tox *tox, uint32_t *list) { if (list) { const Messenger *m = tox; //TODO: size parameter? - copy_friendlist(m, list, tox_friend_list_size(tox)); + copy_friendlist(m, list, tox_self_get_friend_list_size(tox)); } } @@ -965,7 +965,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, return 0; case -6: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_SENDQ); return 0; case -7: diff --git a/toxcore/tox.h b/toxcore/tox.h index 1457a70b..f1b8b893 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -210,6 +210,11 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); */ #define TOX_PUBLIC_KEY_SIZE 32 +/** + * The size of a Tox Secret Key in bytes. + */ +#define TOX_SECRET_KEY_SIZE 32 + /** * The size of a Tox address in bytes. Tox addresses are in the format * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. @@ -344,7 +349,7 @@ struct Tox_Options { * * This member is ignored (it can be NULL) if proxy_enabled is false. */ - char *proxy_address; + const char *proxy_host; /** * The port to use to connect to the proxy server. @@ -443,9 +448,9 @@ typedef enum TOX_ERR_NEW { /** * proxy_type was invalid. */ - TOX_ERR_PROXY_TYPE, + TOX_ERR_NEW_PROXY_BAD_TYPE, /** - * proxy_type was valid but the proxy_address passed had an invalid format + * proxy_type was valid but the proxy_host passed had an invalid format * or was NULL. */ TOX_ERR_NEW_PROXY_BAD_HOST, @@ -454,7 +459,7 @@ typedef enum TOX_ERR_NEW { */ TOX_ERR_NEW_PROXY_BAD_PORT, /** - * The proxy address passed could not be resolved. + * The proxy host passed could not be resolved. */ TOX_ERR_NEW_PROXY_NOT_FOUND, /** @@ -542,10 +547,10 @@ typedef enum TOX_ERR_BOOTSTRAP { TOX_ERR_BOOTSTRAP_OK, TOX_ERR_BOOTSTRAP_NULL, /** - * The address could not be resolved to an IP address, or the IP address + * The host could not be resolved to an IP address, or the IP address * passed was invalid. */ - TOX_ERR_BOOTSTRAP_BAD_ADDRESS, + TOX_ERR_BOOTSTRAP_BAD_HOST, /** * The port passed was invalid. The valid port range is (1, 65535). */ @@ -564,14 +569,14 @@ typedef enum TOX_ERR_BOOTSTRAP { * also use the TCP connection when NAT hole punching is slow, and later switch * to UDP if hole punching succeeds. * - * @param address The hostname or IP address (IPv4 or IPv6) of the node. + * @param host The hostname or IP address (IPv4 or IPv6) of the node. * @param port The port on the host on which the bootstrap Tox instance is * listening. * @param public_key The long term public key of the bootstrap node * (TOX_PUBLIC_KEY_SIZE bytes). * @return true on success. */ -bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); +bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); /** @@ -581,13 +586,13 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t * * the same bootstrap node, or to add TCP relays without using them as * bootstrap nodes. * - * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay. + * @param host The hostname or IP address (IPv4 or IPv6) of the TCP relay. * @param port The port on the host on which the TCP relay is listening. * @param public_key The long term public key of the TCP relay * (TOX_PUBLIC_KEY_SIZE bytes). * @return true on success. */ -bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, +bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); @@ -697,7 +702,7 @@ void tox_self_get_public_key(const Tox *tox, uint8_t *public_key); /** * Copy the secret key from the Tox object. * - * @param secret_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If + * @param secret_key A memory region of at least TOX_SECRET_KEY_SIZE bytes. If * this parameter is NULL, this function has no effect. */ void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key); @@ -978,20 +983,20 @@ bool tox_friend_exists(const Tox *tox, uint32_t friend_number); * Return the number of friends on the friend list. * * This function can be used to determine how much memory to allocate for - * tox_friend_list. + * tox_self_get_friend_list. */ -size_t tox_friend_list_size(const Tox *tox); +size_t tox_self_get_friend_list_size(const Tox *tox); /** * Copy a list of valid friend numbers into an array. * - * Call tox_friend_list_size to determine the number of elements to allocate. + * Call tox_self_get_friend_list_size to determine the number of elements to allocate. * * @param list A memory region with enough space to hold the friend list. If * this parameter is NULL, this function has no effect. */ -void tox_friend_get_list(const Tox *tox, uint32_t *list); +void tox_self_get_friend_list(const Tox *tox, uint32_t *list); @@ -1096,7 +1101,7 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8 * tox_friend_get_status_message_size. */ typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, - void *user_data); + void *user_data); /** * Set the callback for the `friend_status_message` event. Pass NULL to unset. @@ -1155,7 +1160,7 @@ TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_ * tox_friend_get_connection_status on the passed friend_number. */ typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, - void *user_data); + void *user_data); /** * Set the callback for the `friend_connection_status` event. Pass NULL to @@ -1655,7 +1660,7 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { /** * Packet queue is full. */ - TOX_ERR_FILE_SEND_CHUNK_QUEUE_FULL, + TOX_ERR_FILE_SEND_CHUNK_SENDQ, /** * Position parameter was wrong. */ @@ -1893,7 +1898,7 @@ bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uin * @param length The length of the packet data byte array. */ typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, - void *user_data); + void *user_data); /** * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset. From 24c70c9e8479a528e02afefa4afc5c3219f9afd7 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 13:44:48 -0400 Subject: [PATCH 077/101] Added and implemented file_id parameter to file tranfers. file_id is a 32byte identifier that can be used by users to identify file tranfers across core/client restarts in order to resume broken file tranfers. In avatar tranfers it corresponds to the hash of the avatar. Added tox_file_get_file_id() function to api to obtain the file_id of an ongoing file transfer. If not set, core will generate a random one. --- auto_tests/tox_test.c | 29 +++++++++++++-- testing/nTox.c | 4 +-- testing/tox_sync.c | 4 +-- toxcore/Messenger.c | 82 ++++++++++++++++++++++++++++++++++--------- toxcore/Messenger.h | 14 +++++++- toxcore/tox.c | 33 +++++++++++++---- toxcore/tox.h | 52 ++++++++++++++++++++------- 7 files changed, 177 insertions(+), 41 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index dc23040d..942931a1 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -100,6 +100,7 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size return; } +uint8_t file_cmp_id[TOX_FILE_ID_LENGTH]; uint8_t filenum; uint32_t file_accepted; uint64_t file_size; @@ -119,6 +120,22 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui 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; TOX_ERR_FILE_CONTROL error; @@ -520,10 +537,18 @@ START_TEST(test_few_clients) tox_callback_file_recv_control(tox3, file_print_control, &to_compare); tox_callback_file_receive(tox3, tox_file_receive, &to_compare); uint64_t totalf_size = 100 * 1024 * 1024; - uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), - 0); + 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) { tox_iterate(tox1); diff --git a/testing/nTox.c b/testing/nTox.c index d60d57f4..a0101b6b 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -158,8 +158,8 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, - 0); + 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; diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 603c6f22..8c693793 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -88,8 +88,8 @@ uint32_t add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, filesize, (uint8_t *)filename, strlen(filename) + 1, - 0); + 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; diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 911c92da..39572dd0 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1023,13 +1023,58 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_ #define MAX_FILENAME_LENGTH 255 +/* 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) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -2; + + uint32_t temp_filenum; + uint8_t send_receive, file_number; + + if (filenumber >= (1 << 16)) { + send_receive = 1; + temp_filenum = (filenumber >> 16) - 1; + } else { + send_receive = 0; + temp_filenum = filenumber; + } + + if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) + return -2; + + file_number = temp_filenum; + + struct File_Transfers *ft; + + if (send_receive) { + ft = &m->friendlist[friendnumber].file_receiving[file_number]; + } else { + ft = &m->friendlist[friendnumber].file_sending[file_number]; + } + + if (ft->status == FILESTATUS_NONE) + return -2; + + memcpy(file_id, ft->id, FILE_ID_LENGTH); + return 0; +} + /* Send a file send request. * Maximum filename length is 255 bytes. * return 1 on success * return 0 on failure */ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, - uint64_t filesize, const uint8_t *filename, uint16_t filename_length) + uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) { if (friend_not_valid(m, friendnumber)) return 0; @@ -1037,13 +1082,18 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi if (filename_length > MAX_FILENAME_LENGTH) return 0; - uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + filename_length]; + uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length]; packet[0] = filenumber; file_type = htonl(file_type); memcpy(packet + 1, &file_type, sizeof(file_type)); host_to_net((uint8_t *)&filesize, sizeof(filesize)); memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize)); - memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), filename, filename_length); + memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), file_id, FILE_ID_LENGTH); + + if (filename_length) { + memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length); + } + return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, sizeof(packet), 0); } @@ -1057,7 +1107,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi * */ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length) + const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) { if (friend_not_valid(m, friendnumber)) return -1; @@ -1078,7 +1128,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (i == MAX_CONCURRENT_FILE_PIPES) return -3; - if (file_sendrequest(m, friendnumber, i, file_type, filesize, filename, filename_length) == 0) + if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) return -4; struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; @@ -1088,6 +1138,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ ft->requested = 0; ft->slots_allocated = 0; ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, file_id, FILE_ID_LENGTH); ++m->friendlist[friendnumber].num_sending_files; @@ -1932,9 +1983,9 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_FILE_SENDREQUEST: { - const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t); + const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH; - if (data_length < head_length + 1) + if (data_length < head_length) break; uint8_t filenumber = data[0]; @@ -1944,16 +1995,15 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) memcpy(&file_type, data + 1, sizeof(file_type)); file_type = ntohl(file_type); - /* Check if the name is the right size if file is avatar. */ - if (file_type == FILEKIND_AVATAR && filename_length != crypto_hash_sha256_BYTES) - break; - memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); net_to_host((uint8_t *) &filesize, sizeof(filesize)); - m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; - m->friendlist[i].file_receiving[filenumber].size = filesize; - m->friendlist[i].file_receiving[filenumber].transferred = 0; - m->friendlist[i].file_receiving[filenumber].paused = FILE_PAUSE_NOT; + struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; + + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); /* Force NULL terminate file name. */ uint8_t filename_terminated[filename_length + 1]; @@ -1965,7 +2015,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) real_filenumber <<= 16; if (m->file_sendrequest) - (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename_terminated, filename_length, + (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, m->file_sendrequest_userdata); break; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 716ac851..94cff062 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -125,6 +125,8 @@ typedef enum { } USERSTATUS; +#define FILE_ID_LENGTH 32 + struct File_Transfers { uint64_t size; uint64_t transferred; @@ -133,6 +135,7 @@ struct File_Transfers { 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, @@ -610,6 +613,15 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u 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 @@ -620,7 +632,7 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_ * */ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length); + const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length); /* Send a file control request. * diff --git a/toxcore/tox.c b/toxcore/tox.c index da109502..b793bd8c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -889,21 +889,42 @@ void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function callback_file_control(m, function, user_data); } -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, - size_t filename_length, TOX_ERR_FILE_SEND *error) +bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, + TOX_ERR_FILE_GET *error) +{ + const Messenger *m = tox; + int ret = file_get_id(m, friend_number, file_number, file_id); + + if (ret == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK); + return 1; + } else if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND); + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND); + } + + return 0; +} + +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, + const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) { if (!filename) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); return UINT32_MAX; } - if (!filename_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_EMPTY); - return UINT32_MAX; + uint8_t f_id[FILE_ID_LENGTH]; + + if (!file_id) { + /* Tox keys are 32 bytes like FILE_ID_LENGTH. */ + new_symmetric_key(f_id); + file_id = f_id; } Messenger *m = tox; - long int file_num = new_filesender(m, friend_number, kind, file_size, filename, filename_length); + long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length); if (file_num >= 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); diff --git a/toxcore/tox.h b/toxcore/tox.h index f1b8b893..b255de5e 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -255,6 +255,11 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); */ #define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 +/** + * The number of bytes in a file id. + */ +#define TOX_FILE_ID_LENGTH 32 + /******************************************************************************* * * :: Global enumerations @@ -1412,9 +1417,9 @@ enum TOX_FILE_KIND { * * Clients who receive avatar send requests can reject it (by sending * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by - * sending TOX_FILE_CONTROL_RESUME). The filename of length TOX_HASH_LENGTH bytes - * will contain the hash. A client can compare this hash with a - * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar + * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes + * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare + * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar * transfer if it matches. */ TOX_FILE_KIND_AVATAR @@ -1534,6 +1539,32 @@ typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); +typedef enum TOX_ERR_FILE_GET { + TOX_ERR_FILE_GET_OK, + /** + * The friend_number passed did not designate a valid friend. + */ + TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, + /** + * No file transfer with the given file number was found for the given friend. + */ + TOX_ERR_FILE_GET_NOT_FOUND +} TOX_ERR_FILE_GET; + +/** + * Copy the file id associated to the file transfer to a byte array. + * + * @param friend_number The friend number of the friend the file is being + * transferred to. + * @param file_number The friend-specific identifier for the file transfer. + * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If + * this parameter is NULL, this function has no effect. + * + * @return true on success. + */ +bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, + TOX_ERR_FILE_GET *error); + /******************************************************************************* * * :: File transmission: sending @@ -1557,8 +1588,7 @@ typedef enum TOX_ERR_FILE_SEND { */ TOX_ERR_FILE_SEND_NAME_EMPTY, /** - * Filename length exceeded 255 bytes or if kind was equal to TOX_FILE_KIND_AVATAR - * the length was not TOX_HASH_LENGTH. + * Filename length exceeded 255 bytes. */ TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH, /** @@ -1581,11 +1611,6 @@ typedef enum TOX_ERR_FILE_SEND { * File transmission occurs in chunks, which are requested through the * `file_request_chunk` event. * - * File numbers are stable across tox_save/tox_load cycles, so that file - * transfers can be resumed when a client restarts. The client needs to - * associate (friend Public Key, file number) with the local path of the file and - * persist this information to support resuming of transfers across restarts. - * * If the file contents change during a transfer, the behaviour is unspecified * in general. What will actually happen depends on the mode in which the file * was modified and how the client determines the file size. @@ -1616,6 +1641,9 @@ typedef enum TOX_ERR_FILE_SEND { * @param kind The meaning of the file to be sent. * @param file_size Size in bytes of the file the client wants to send, 0 if * unknown or streaming. + * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to + * uniquely identify file transfers across core restarts. If NULL, a random one will + * be generated by core. It can then be obtained by using tox_file_get_file_id(). * @param filename Name of the file. Does not need to be the actual name. This * name will be sent along with the file send request. * @param filename_length Size in bytes of the filename. @@ -1624,8 +1652,8 @@ typedef enum TOX_ERR_FILE_SEND { * number is per friend. File numbers are reused after a transfer terminates. * on failure, this function returns UINT32_MAX. */ -uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, - size_t filename_length, TOX_ERR_FILE_SEND *error); +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, + const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); typedef enum TOX_ERR_FILE_SEND_CHUNK { From e072079620d7353fc06e1c2ba6d4b5228d444422 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 13:47:09 -0400 Subject: [PATCH 078/101] Allow file names to be of length 0. Pointer in callback will be NULL if length is 0. --- toxcore/Messenger.c | 14 ++++++++------ toxcore/tox.c | 2 +- toxcore/tox.h | 4 ---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 39572dd0..e85e5ee0 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1115,9 +1115,6 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (filename_length > MAX_FILENAME_LENGTH) return -2; - if (file_type == FILEKIND_AVATAR && filename_length != crypto_hash_sha256_BYTES) - return -2; - uint32_t i; for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { @@ -2005,10 +2002,15 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) ft->paused = FILE_PAUSE_NOT; memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); - /* Force NULL terminate file name. */ uint8_t filename_terminated[filename_length + 1]; - memcpy(filename_terminated, data + head_length, filename_length); - filename_terminated[filename_length] = 0; + uint8_t *filename = NULL; + + if (filename_length) { + /* Force NULL terminate file name. */ + memcpy(filename_terminated, data + head_length, filename_length); + filename_terminated[filename_length] = 0; + filename = filename_terminated; + } uint32_t real_filenumber = filenumber; real_filenumber += 1; diff --git a/toxcore/tox.c b/toxcore/tox.c index b793bd8c..36f87cc6 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -910,7 +910,7 @@ bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) { - if (!filename) { + if (filename_length && !filename) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); return UINT32_MAX; } diff --git a/toxcore/tox.h b/toxcore/tox.h index b255de5e..8587dfa9 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1583,10 +1583,6 @@ typedef enum TOX_ERR_FILE_SEND { * This client is currently not connected to the friend. */ TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED, - /** - * Filename length was 0. - */ - TOX_ERR_FILE_SEND_NAME_EMPTY, /** * Filename length exceeded 255 bytes. */ From ea8d27259f7d0314b08f6eb32edf15fec3822530 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 15:05:17 -0400 Subject: [PATCH 079/101] Added tox_file_send_seek() function to api. This function can be used to seek an incoming file tranfer right before accepting it. It is meant to be used to resume incomplete file tranfers by clients. --- auto_tests/tox_test.c | 27 ++++++++++--- toxcore/Messenger.c | 91 +++++++++++++++++++++++++++++++++++++++++-- toxcore/Messenger.h | 15 ++++++- toxcore/tox.c | 42 ++++++++++++++++++++ toxcore/tox.h | 42 ++++++++++++++++++++ 5 files changed, 206 insertions(+), 11 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 942931a1..31f65505 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -100,6 +100,9 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size return; } +uint64_t size_recv; +uint64_t sending_pos; + uint8_t file_cmp_id[TOX_FILE_ID_LENGTH]; uint8_t filenum; uint32_t file_accepted; @@ -137,6 +140,15 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui } file_size = filesize; + sending_pos = size_recv = 1337; + + TOX_ERR_FILE_SEEK err_s; + + if (!tox_file_send_seek(tox, friend_number, file_number, 1337, &err_s)) { + ck_abort_msg("tox_file_send_seek error"); + } + + ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_send_seek wrong error"); TOX_ERR_FILE_CONTROL error; @@ -145,6 +157,12 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui } else { ck_abort_msg("tox_file_send_control failed. %i", error); } + + if (tox_file_send_seek(tox, friend_number, file_number, 1234, &err_s)) { + ck_abort_msg("tox_file_send_seek no error"); + } + + ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_send_seek wrong error"); } uint32_t sendf_ok; @@ -160,7 +178,6 @@ void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, } uint8_t sending_num; -uint64_t sending_pos; _Bool file_sending_done; void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, void *user_data) @@ -173,7 +190,7 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb } if (sending_pos != position) { - ck_abort_msg("Bad position"); + ck_abort_msg("Bad position %llu", position); return; } @@ -199,7 +216,6 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb } -uint64_t size_recv; uint8_t num; _Bool file_recv; void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, @@ -549,7 +565,6 @@ START_TEST(test_few_clients) 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); @@ -559,8 +574,8 @@ START_TEST(test_few_clients) if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv) { break; } else { - ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u", sendf_ok, file_recv, totalf_size == file_size, - size_recv == file_size, sending_pos == size_recv); + ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv, + totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, totalf_size, size_recv, sending_pos); } } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index e85e5ee0..e4d45779 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1155,7 +1155,7 @@ int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t s packet[2] = control_type; if (data_length) { - memcpy(packet, packet + 3, data_length); + memcpy(packet + 3, data, data_length); } return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, sizeof(packet), 0); @@ -1247,6 +1247,71 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, return 0; } +/* 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) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) + return -2; + + uint32_t temp_filenum; + uint8_t send_receive, file_number; + + if (filenumber >= (1 << 16)) { + send_receive = 1; + temp_filenum = (filenumber >> 16) - 1; + } else { + return -4; + } + + if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) + return -3; + + file_number = temp_filenum; + + struct File_Transfers *ft; + + if (send_receive) { + ft = &m->friendlist[friendnumber].file_receiving[file_number]; + } else { + ft = &m->friendlist[friendnumber].file_sending[file_number]; + } + + if (ft->status == FILESTATUS_NONE) + return -3; + + if (ft->status != FILESTATUS_NOT_ACCEPTED) + return -5; + + if (ft->size && position > ft->size) { + return -6; + } + + uint64_t sending_pos = position; + host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos)); + + if (send_file_control_packet(m, friendnumber, send_receive, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos, + sizeof(sending_pos))) { + ft->transferred = position; + } else { + return -8; + } + + return 0; +} + /* return packet number on success. * return -1 on failure. */ @@ -1473,7 +1538,7 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv if (receive_send > 1) return -1; - if (control_type > FILECONTROL_RESUME_BROKEN) + if (control_type > FILECONTROL_SEEK) return -1; uint32_t real_filenumber = filenumber; @@ -1518,8 +1583,26 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv --m->friendlist[friendnumber].num_sending_files; } - } else if (control_type == FILECONTROL_RESUME_BROKEN) { - //TODO + } else if (control_type == FILECONTROL_SEEK) { + uint64_t position; + + if (length != sizeof(position)) { + return -1; + } + + /* seek can only be sent by the receiver to seek before resuming broken tranfers. */ + if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) { + return -1; + } + + memcpy(&position, data, sizeof(position)); + net_to_host((uint8_t *) &position, sizeof(position)); + + if (ft->size && position > ft->size) { + return -1; + } + + ft->transferred = ft->requested = position; } else { return -1; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 94cff062..827a3298 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -159,7 +159,7 @@ enum { FILECONTROL_ACCEPT, FILECONTROL_PAUSE, FILECONTROL_KILL, - FILECONTROL_RESUME_BROKEN + FILECONTROL_SEEK }; enum { @@ -648,6 +648,19 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ */ 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 0 on success diff --git a/toxcore/tox.c b/toxcore/tox.c index 36f87cc6..87b8e8de 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -883,6 +883,48 @@ bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_numbe return 0; } +bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + TOX_ERR_FILE_SEEK *error) +{ + Messenger *m = tox; + int ret = file_seek(m, friend_number, file_number, position); + + if (ret == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK); + return 1; + } + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND); + return 0; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED); + return 0; + + case -3: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND); + return 0; + + case -4: + case -5: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED); + return 0; + + case -6: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION); + return 0; + + case -8: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SEND_FAILED); + return 0; + } + + /* can't happen */ + return 0; +} + void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data) { Messenger *m = tox; diff --git a/toxcore/tox.h b/toxcore/tox.h index 8587dfa9..ce5a5b56 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1539,6 +1539,48 @@ typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); +typedef enum TOX_ERR_FILE_SEEK { + TOX_ERR_FILE_SEEK_OK, + /** + * The friend_number passed did not designate a valid friend. + */ + TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND, + /** + * This client is currently not connected to the friend. + */ + TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED, + /** + * No file transfer with the given file number was found for the given friend. + */ + TOX_ERR_FILE_SEEK_NOT_FOUND, + /** + * File was not in a state where it could be seeked. + */ + TOX_ERR_FILE_SEEK_DENIED, + /** + * Seek position was invalid + */ + TOX_ERR_FILE_SEEK_INVALID_POSITION, + /** + * Packet failed to send. + */ + TOX_ERR_FILE_SEEK_SEND_FAILED +} TOX_ERR_FILE_SEEK; + +/** + * Sends a file seek control command to a friend for a given file transfer. + * + * This function can only be called to resume a file transfer right before + * TOX_FILE_CONTROL_RESUME is sent. + * + * @param friend_number The friend number of the friend the file is being + * transferred to. + * @param file_number The friend-specific identifier for the file transfer. + * @param position The position that the file should be seeked to. + */ +bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + TOX_ERR_FILE_SEEK *error); + typedef enum TOX_ERR_FILE_GET { TOX_ERR_FILE_GET_OK, /** From e778bfb42fd08e84dade642ea9d1ada3243b3dcd Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 16:00:03 -0400 Subject: [PATCH 080/101] Changed INVALID_LENGTH to TOO_LONG. --- toxcore/tox.c | 2 +- toxcore/tox.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 87b8e8de..55711352 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -979,7 +979,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t return UINT32_MAX; case -2: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG); return UINT32_MAX; case -3: diff --git a/toxcore/tox.h b/toxcore/tox.h index ce5a5b56..0b9a63ba 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1628,7 +1628,7 @@ typedef enum TOX_ERR_FILE_SEND { /** * Filename length exceeded 255 bytes. */ - TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH, + TOX_ERR_FILE_SEND_NAME_TOO_LONG, /** * Too many ongoing transfers. The maximum number of concurrent file transfers * is 256 per friend per direction (sending and receiving). From 67f6d0857afbd915c0d6668656d1207f574f1d1d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 16:02:46 -0400 Subject: [PATCH 081/101] Make sure some defines in the public api are always correct. Make sure some assumptions are always correct. --- toxcore/tox.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/toxcore/tox.c b/toxcore/tox.c index 55711352..47f4f6a3 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -38,6 +38,38 @@ typedef struct Messenger Tox; #define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} +#if TOX_HASH_LENGTH != crypto_hash_sha256_BYTES +#error TOX_HASH_LENGTH is assumed to be equal to crypto_hash_sha256_BYTES +#endif + +#if FILE_ID_LENGTH != crypto_box_KEYBYTES +#error FILE_ID_LENGTH is assumed to be equal to crypto_box_KEYBYTES +#endif + +#if TOX_FILE_ID_LENGTH != crypto_box_KEYBYTES +#error TOX_FILE_ID_LENGTH is assumed to be equal to crypto_box_KEYBYTES +#endif + +#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH +#error TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH +#endif + +#if TOX_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES +#error TOX_PUBLIC_KEY_SIZE is assumed to be equal to crypto_box_PUBLICKEYBYTES +#endif + +#if TOX_SECRET_KEY_SIZE != crypto_box_SECRETKEYBYTES +#error TOX_SECRET_KEY_SIZE is assumed to be equal to crypto_box_SECRETKEYBYTES +#endif + +#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH +#error TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH +#endif + +#if TOX_MAX_STATUS_MESSAGE_LENGTH != MAX_STATUSMESSAGE_LENGTH +#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH +#endif + uint32_t tox_version_major(void) { return 0; From 8286c2c22fc110dcc58c981eb39dd7bf46ae8aa9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 16:20:38 -0400 Subject: [PATCH 082/101] Save function renamed to tox_get_savedata() --- auto_tests/tox_test.c | 4 ++-- testing/nTox.c | 4 ++-- toxcore/tox.c | 4 ++-- toxcore/tox.h | 13 +++++++------ toxencryptsave/toxencryptsave.c | 10 +++++----- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 31f65505..42ba65c7 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -305,9 +305,9 @@ START_TEST(test_one) tox_self_set_name(tox1, name, sizeof(name), 0); ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH"); - size_t save_size = tox_save_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); TOX_ERR_NEW err_n; diff --git a/testing/nTox.c b/testing/nTox.c index a0101b6b..9e114ba5 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -965,9 +965,9 @@ static int save_data(Tox *m) } int res = 1; - size_t size = tox_save_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); diff --git a/toxcore/tox.c b/toxcore/tox.c index 47f4f6a3..297e7796 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -224,13 +224,13 @@ void tox_kill(Tox *tox) logger_kill_global(); } -size_t tox_save_size(const Tox *tox) +size_t tox_get_savedata_size(const Tox *tox) { const Messenger *m = tox; return messenger_size(m); } -void tox_save(const Tox *tox, uint8_t *data) +void tox_get_savedata(const Tox *tox, uint8_t *data) { if (data) { const Messenger *m = tox; diff --git a/toxcore/tox.h b/toxcore/tox.h index 0b9a63ba..2625040f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -497,14 +497,14 @@ typedef enum TOX_ERR_NEW { * loop with a new instance will operate correctly. * * If the data parameter is not NULL, this function will load the Tox instance - * from a byte array previously filled by tox_save. + * from a byte array previously filled by tox_get_savedata. * * If loading failed or succeeded only partially, the new or partially loaded * instance is returned and an error code is set. * * @param options An options object as described above. If this parameter is * NULL, the default options are used. - * @param data A byte array containing data previously stored by tox_save. + * @param data A byte array containing data previously stored by tox_get_savedata. * @param length The length of the byte array data. If this parameter is 0, the * data parameter is ignored. * @@ -525,20 +525,21 @@ void tox_kill(Tox *tox); /** * Calculates the number of bytes required to store the tox instance with - * tox_save. This function cannot fail. The result is always greater than 0. + * tox_get_savedata. This function cannot fail. The result is always greater + * than 0. * * @see threading for concurrency implications. */ -size_t tox_save_size(const Tox *tox); +size_t tox_get_savedata_size(const Tox *tox); /** * Store all information associated with the tox instance to a byte array. * * @param data A memory region large enough to store the tox instance data. - * Call tox_save_size to find the number of bytes required. If this parameter + * Call tox_get_savedata_size to find the number of bytes required. If this parameter * is NULL, this function has no effect. */ -void tox_save(const Tox *tox, uint8_t *data); +void tox_get_savedata(const Tox *tox, uint8_t *data); /******************************************************************************* diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index f9846ac9..587c7048 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -66,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_save_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 @@ -205,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_save_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); @@ -222,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_save_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); From 0beaa2fdb4a4621b822f5494567090bed1b8248f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 17:13:25 -0400 Subject: [PATCH 083/101] Renamed SEND_FAILED to SENDQ. --- toxcore/tox.c | 4 ++-- toxcore/tox.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index 297e7796..f245993f 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -907,7 +907,7 @@ bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_numbe return 0; case -8: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SEND_FAILED); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SENDQ); return 0; } @@ -949,7 +949,7 @@ bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, return 0; case -8: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SEND_FAILED); + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SENDQ); return 0; } diff --git a/toxcore/tox.h b/toxcore/tox.h index 2625040f..373786ae 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1498,9 +1498,9 @@ typedef enum TOX_ERR_FILE_CONTROL { */ TOX_ERR_FILE_CONTROL_ALREADY_PAUSED, /** - * Packet failed to send. + * Packet queue is full. */ - TOX_ERR_FILE_CONTROL_SEND_FAILED + TOX_ERR_FILE_CONTROL_SENDQ } TOX_ERR_FILE_CONTROL; /** @@ -1563,9 +1563,9 @@ typedef enum TOX_ERR_FILE_SEEK { */ TOX_ERR_FILE_SEEK_INVALID_POSITION, /** - * Packet failed to send. + * Packet queue is full. */ - TOX_ERR_FILE_SEEK_SEND_FAILED + TOX_ERR_FILE_SEEK_SENDQ } TOX_ERR_FILE_SEEK; /** From ad87dbb470cb9b223c66727ab6ad615f46e73a37 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 17:23:47 -0400 Subject: [PATCH 084/101] Kill all file transfers associated with the friend when friend goes offline. --- toxcore/Messenger.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index e4d45779..176e80b5 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1515,19 +1515,20 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) } /* Run this when the friend disconnects. - * Sets all current file transfers to broken. + * Kill all current file transfers. */ static void break_files(const Messenger *m, int32_t friendnumber) { uint32_t i; - /* TODO - for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { - if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) - m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_BROKEN; - if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) - m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_BROKEN; - }*/ + //TODO: Inform the client which file transfers get killed with a callback? + for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { + if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) + m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NONE; + + if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) + m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_NONE; + } } /* return -1 on failure, 0 on success. From 5b7cbc89560828c2f5b0b2d1f4cdd738da0797a0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Mar 2015 12:54:00 -0400 Subject: [PATCH 085/101] Api changes. receive to recv in file receive functions. Added TOX_MAX_FILENAME_LENGTH define. --- auto_tests/tox_test.c | 4 ++-- testing/nTox.c | 4 ++-- testing/tox_sync.c | 4 ++-- toxcore/tox.c | 4 ++-- toxcore/tox.h | 21 +++++++++++++-------- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 42ba65c7..6a318fe0 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -547,11 +547,11 @@ START_TEST(test_few_clients) file_accepted = file_size = file_recv = sendf_ok = size_recv = 0; long long unsigned int f_time = time(NULL); - tox_callback_file_receive_chunk(tox3, write_file, &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_request_chunk(tox2, tox_file_request_chunk, &to_compare); tox_callback_file_recv_control(tox3, file_print_control, &to_compare); - tox_callback_file_receive(tox3, tox_file_receive, &to_compare); + tox_callback_file_recv(tox3, tox_file_receive, &to_compare); uint64_t totalf_size = 100 * 1024 * 1024; uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), 0); diff --git a/testing/nTox.c b/testing/nTox.c index 9e114ba5..9a043172 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1269,9 +1269,9 @@ int main(int argc, char *argv[]) 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_receive_chunk(m, write_file, NULL); + tox_callback_file_recv_chunk(m, write_file, NULL); tox_callback_file_recv_control(m, file_print_control, NULL); - tox_callback_file_receive(m, file_request_accept, NULL); + tox_callback_file_recv(m, file_request_accept, NULL); tox_callback_file_request_chunk(m, tox_file_request_chunk, NULL); tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL); diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 8c693793..5c9af02e 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -230,9 +230,9 @@ int main(int argc, char *argv[]) } Tox *tox = tox_new(0, 0, 0, 0); - tox_callback_file_receive_chunk(tox, write_file, NULL); + tox_callback_file_recv_chunk(tox, write_file, NULL); tox_callback_file_recv_control(tox, file_print_control, NULL); - tox_callback_file_receive(tox, file_request_accept, NULL); + tox_callback_file_recv(tox, file_request_accept, NULL); tox_callback_file_request_chunk(tox, tox_file_request_chunk, NULL); tox_callback_friend_connection_status(tox, print_online, NULL); diff --git a/toxcore/tox.c b/toxcore/tox.c index f245993f..04218ef2 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1078,13 +1078,13 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi callback_file_reqchunk(m, function, user_data); } -void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *user_data) +void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_data) { Messenger *m = tox; callback_file_sendrequest(m, function, user_data); } -void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *function, void *user_data) +void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function, void *user_data) { Messenger *m = tox; callback_file_data(m, function, user_data); diff --git a/toxcore/tox.h b/toxcore/tox.h index 373786ae..c4e9cf14 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -260,6 +260,11 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); */ #define TOX_FILE_ID_LENGTH 32 +/** + * Maximum file name length for file tran. + */ +#define TOX_MAX_FILENAME_LENGTH 255 + /******************************************************************************* * * :: Global enumerations @@ -1627,7 +1632,7 @@ typedef enum TOX_ERR_FILE_SEND { */ TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED, /** - * Filename length exceeded 255 bytes. + * Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes. */ TOX_ERR_FILE_SEND_NAME_TOO_LONG, /** @@ -1640,7 +1645,7 @@ typedef enum TOX_ERR_FILE_SEND { /** * Send a file transmission request. * - * Maximum filename length is 255 bytes. The filename should generally just be + * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename should generally just be * a file name, not a path with directory names. * * If a non-zero file size is provided, this can be used by both sides to @@ -1805,15 +1810,15 @@ void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *functi * @param file_number The friend-specific file number the data received is * associated with. */ -typedef void tox_file_receive_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, - uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); +typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, + uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); /** * Set the callback for the `file_receive` event. Pass NULL to unset. * * This event is triggered when a file transfer request is received. */ -void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *user_data); +void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_data); /** @@ -1837,13 +1842,13 @@ void tox_callback_file_receive(Tox *tox, tox_file_receive_cb *function, void *us * @param data A byte array containing the received chunk. * @param length The length of the received chunk. */ -typedef void tox_file_receive_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, - const uint8_t *data, size_t length, void *user_data); +typedef void tox_file_recv_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + const uint8_t *data, size_t length, void *user_data); /** * Set the callback for the `file_receive_chunk` event. Pass NULL to unset. */ -void tox_callback_file_receive_chunk(Tox *tox, tox_file_receive_chunk_cb *function, void *user_data); +void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function, void *user_data); /******************************************************************************* From b9e747fd50a81496626deaaf4878f06630abc75a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Mar 2015 14:39:52 -0400 Subject: [PATCH 086/101] When friend goes offline all his file transfers get removed. This is now documented in the API. Ported programs in testing/ to this behaviour. --- testing/nTox.c | 17 +++++++++++++++++ testing/tox_sync.c | 16 +++++++++++++++- toxcore/tox.h | 3 +++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/testing/nTox.c b/testing/nTox.c index 9a043172..ff4fe8ac 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1195,6 +1195,22 @@ void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t p 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 == friend_number) { + fclose(file_senders[i].file); + file_senders[i].file = 0; + } + } +} + char timeout_getch(Tox *m) { char c; @@ -1274,6 +1290,7 @@ int main(int argc, char *argv[]) tox_callback_file_recv(m, file_request_accept, NULL); tox_callback_file_request_chunk(m, tox_file_request_chunk, NULL); tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL); + tox_callback_friend_connection_status(tox, print_online, NULL); initscr(); noecho(); diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 5c9af02e..ea85c278 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -211,8 +211,22 @@ void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void * { 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[]) diff --git a/toxcore/tox.h b/toxcore/tox.h index c4e9cf14..29eb126a 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1655,6 +1655,9 @@ typedef enum TOX_ERR_FILE_SEND { * File transmission occurs in chunks, which are requested through the * `file_request_chunk` event. * + * When a friend goes offline, all file transfers associated with the friend are + * purged from core. + * * If the file contents change during a transfer, the behaviour is unspecified * in general. What will actually happen depends on the mode in which the file * was modified and how the client determines the file size. From 2f65de6fd1a3c83e0754898ab45da006917223ff Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 18 Mar 2015 14:18:36 -0500 Subject: [PATCH 087/101] Move get_connection_status to self pseudonamespace, to contrast friend_get_connection_status --- auto_tests/tox_test.c | 4 ++-- auto_tests/toxav_basic_test.c | 2 +- auto_tests/toxav_many_test.c | 10 +++++----- testing/nTox.c | 2 +- testing/tox_shell.c | 2 +- testing/tox_sync.c | 2 +- toxcore/tox.c | 4 ++-- toxcore/tox.h | 14 +++++++------- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 42ba65c7..adf33424 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -359,7 +359,7 @@ START_TEST(test_few_clients) uint32_t to_compare = 974536; connected_t1 = 0; - tox_callback_connection_status(tox1, tox_connection_status, &to_compare); + 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_ADDRESS_SIZE]; tox_self_get_address(tox2, address); @@ -373,7 +373,7 @@ START_TEST(test_few_clients) tox_iterate(tox2); tox_iterate(tox3); - if (tox_get_connection_status(tox1) && tox_get_connection_status(tox2) && tox_get_connection_status(tox3)) { + 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); diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index 3f4a3b8d..4f75b9fb 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -271,7 +271,7 @@ START_TEST(test_AV_flows) tox_iterate(Alice); tox_iterate(Bob); - if (tox_get_connection_status(bootstrap_node) && tox_get_connection_status(Alice) && tox_get_connection_status(Bob) + 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; diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index f22043e1..4287118f 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -302,11 +302,11 @@ START_TEST(test_AV_three_calls) } - if (tox_get_connection_status(bootstrap_node) && - tox_get_connection_status(caller) && - tox_get_connection_status(callees[0]) && - tox_get_connection_status(callees[1]) && - tox_get_connection_status(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; } diff --git a/testing/nTox.c b/testing/nTox.c index 9e114ba5..a6ee9dde 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1313,7 +1313,7 @@ int main(int argc, char *argv[]) while (1) { if (on == 0) { - if (tox_get_connection_status(m)) { + if (tox_self_get_connection_status(m)) { new_lines("[i] connected to DHT"); on = 1; } else { diff --git a/testing/tox_shell.c b/testing/tox_shell.c index 38fe6364..37865b1c 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) uint8_t notconnected = 1; while (1) { - if (tox_get_connection_status(tox) && notconnected) { + if (tox_self_get_connection_status(tox) && notconnected) { printf("\nDHT connected.\n"); notconnected = 0; } diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 8c693793..d60b091e 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -276,7 +276,7 @@ int main(int argc, char *argv[]) uint8_t notconnected = 1; while (1) { - if (tox_get_connection_status(tox) && notconnected) { + if (tox_self_get_connection_status(tox) && notconnected) { printf("\nDHT connected.\n"); notconnected = 0; } diff --git a/toxcore/tox.c b/toxcore/tox.c index f245993f..5d06bd0f 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -319,7 +319,7 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8 return 1; } -TOX_CONNECTION tox_get_connection_status(const Tox *tox) +TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) { const Messenger *m = tox; @@ -335,7 +335,7 @@ TOX_CONNECTION tox_get_connection_status(const Tox *tox) } -void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function, void *user_data) +void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *function, void *user_data) { Messenger *m = tox; m_callback_core_connection(m, function, user_data); diff --git a/toxcore/tox.h b/toxcore/tox.h index 373786ae..778089b7 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -626,20 +626,20 @@ typedef enum TOX_CONNECTION { /** * Return whether we are connected to the DHT. The return value is equal to the - * last value received through the `connection_status` callback. + * last value received through the `self_connection_status` callback. */ -TOX_CONNECTION tox_get_connection_status(const Tox *tox); +TOX_CONNECTION tox_self_get_connection_status(const Tox *tox); /** - * The function type for the `connection_status` callback. + * The function type for the `self_connection_status` callback. * * @param connection_status Equal to the return value of - * tox_get_connection_status. + * tox_self_get_connection_status. */ -typedef void tox_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data); +typedef void tox_self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data); /** - * Set the callback for the `connection_status` event. Pass NULL to unset. + * Set the callback for the `self_connection_status` event. Pass NULL to unset. * * This event is triggered whenever there is a change in the DHT connection * state. When disconnected, a client may choose to call tox_bootstrap again, to @@ -649,7 +649,7 @@ typedef void tox_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status * * TODO: how long should a client wait before bootstrapping again? */ -void tox_callback_connection_status(Tox *tox, tox_connection_status_cb *function, void *user_data); +void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *function, void *user_data); /** From d71136262227d68b649ce9fd8e020597c69cce07 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Mar 2015 15:32:53 -0400 Subject: [PATCH 088/101] Merged normal message function and send action function into one messaging function. This removes code duplication and allows us to easily add new message types to the api without having to add new functions. --- auto_tests/messenger_test.c | 8 ++-- auto_tests/tox_test.c | 11 ++++-- testing/Messenger_test.c | 7 ++-- testing/irc_syncbot.c | 3 +- testing/nTox.c | 11 +++--- testing/tox_shell.c | 5 ++- toxcore/Messenger.c | 60 +++++++----------------------- toxcore/Messenger.h | 41 ++++++++------------ toxcore/tox.c | 35 ++++-------------- toxcore/tox.h | 74 ++++++++++++------------------------- 10 files changed, 86 insertions(+), 169 deletions(-) diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 2e1fe92a..2a813c9b 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -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) == -1); - ck_assert(m_sendmessage(m, REALLY_BIG_NUMBER, (uint8_t *)message, good_len, 0) == -1); - ck_assert(m_sendmessage(m, 17, (uint8_t *)message, good_len, 0) == -1); - ck_assert(m_sendmessage(m, friend_id_num, (uint8_t *)message, bad_len, 0) == -2); + 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 diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 6a318fe0..abffafeb 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -33,11 +33,16 @@ void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *dat } uint32_t messages_received; -void print_message(Tox *m, uint32_t friendnumber, const uint8_t *string, size_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_MESSAGE) { + ck_abort_msg("Bad type"); + } + uint8_t cmp_msg[TOX_MAX_MESSAGE_LENGTH]; memset(cmp_msg, 'G', sizeof(cmp_msg)); @@ -395,9 +400,9 @@ START_TEST(test_few_clients) uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1]; memset(msgs, 'G', sizeof(msgs)); TOX_ERR_FRIEND_SEND_MESSAGE errm; - tox_friend_send_message(tox2, 0, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm); + tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_MESSAGE, 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, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); + tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_MESSAGE, 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) { diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 2e499f77..22e16c38 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -56,10 +56,11 @@ #endif -void print_message(Messenger *m, uint32_t friendnumber, const uint8_t *string, size_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 %lu received from %u: %s \n", length, friendnumber, string); - m_sendmessage(m, friendnumber, (uint8_t *)"Test1", 6, 0); + m_send_message_generic(m, friendnumber, type, (uint8_t *)"Test1", 6, 0); } /* FIXME needed as print_request has to match the interface expected by @@ -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, 0); + 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"); diff --git a/testing/irc_syncbot.c b/testing/irc_syncbot.c index ee49e160..b879e4eb 100644 --- a/testing/irc_syncbot.c +++ b/testing/irc_syncbot.c @@ -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, uint32_t fid, const uint8_t *message, size_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) diff --git a/testing/nTox.c b/testing/nTox.c index ff4fe8ac..a49ab229 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -395,7 +395,7 @@ void line_eval(Tox *m, char *line) int num = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { - if (tox_friend_send_message(m, num, (uint8_t *) *posi + 1, strlen(*posi + 1), NULL) < 1) { + if (tox_friend_send_message(m, num, TOX_MESSAGE_TYPE_MESSAGE, (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); @@ -607,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_friend_send_message(m, friendnumber, (uint8_t *)line, strlen(line), NULL); + uint32_t res = tox_friend_send_message(m, friendnumber, TOX_MESSAGE_TYPE_MESSAGE, (uint8_t *)line, strlen(line), NULL); if (res == 0) { char sss[128]; @@ -881,7 +881,8 @@ void print_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_ do_refresh(); } -void print_message(Tox *m, uint32_t friendnumber, const uint8_t *string, size_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]; @@ -1204,7 +1205,7 @@ void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void * unsigned int i; for (i = 0; i < NUM_FILE_SENDERS; ++i) - if (file_senders[i].file != 0 && file_senders[i].friendnum == friend_number) { + if (file_senders[i].file != 0 && file_senders[i].friendnum == friendnumber) { fclose(file_senders[i].file); file_senders[i].file = 0; } @@ -1290,7 +1291,7 @@ int main(int argc, char *argv[]) tox_callback_file_recv(m, file_request_accept, NULL); tox_callback_file_request_chunk(m, tox_file_request_chunk, NULL); tox_callback_group_namelist_change(m, print_groupnamelistchange, NULL); - tox_callback_friend_connection_status(tox, print_online, NULL); + tox_callback_friend_connection_status(m, print_online, NULL); initscr(); noecho(); diff --git a/testing/tox_shell.c b/testing/tox_shell.c index 38fe6364..a7cef997 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -53,7 +53,8 @@ void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void * printf("\nOther went offline.\n"); } -void print_message(Tox *tox, uint32_t friendnumber, const uint8_t *string, size_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); @@ -148,7 +149,7 @@ int main(int argc, char *argv[]) if (ret <= 0) break; - tox_friend_send_message(tox, num, buf, ret, 0); + tox_friend_send_message(tox, num, TOX_MESSAGE_TYPE_MESSAGE, buf, ret, 0); } tox_iterate(tox); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 176e80b5..ffebdd29 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -455,17 +455,21 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) return 1; } -/* Send a packet_id message. +/* Send a message of type. * * 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. */ -static int send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, - uint8_t packet_id, uint32_t *message_id) +int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length, + uint32_t *message_id) { + if (type > MESSAGE_ACTION) + return -5; + if (friend_not_valid(m, friendnumber)) return -1; @@ -476,7 +480,7 @@ static int send_message_generic(Messenger *m, int32_t friendnumber, const uint8_ return -3; uint8_t packet[length + 1]; - packet[0] = packet_id; + packet[0] = type + PACKET_ID_MESSAGE; if (length != 0) memcpy(packet + 1, message, length); @@ -501,16 +505,6 @@ static int send_message_generic(Messenger *m, int32_t friendnumber, const uint8_ return 0; } -int m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, uint32_t *message_id) -{ - return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE, message_id); -} - -int m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length, uint32_t *message_id) -{ - return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION, message_id); -} - /* Send a name packet to friendnumber. * length is the length with the NULL terminator. */ @@ -812,20 +806,13 @@ void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const } /* Set the function that will be executed when a message from a friend is received. */ -void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_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) { m->friend_message = function; m->friend_message_userdata = userdata; } -void m_callback_action(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), - void *userdata) -{ - m->friend_action = function; - m->friend_action_userdata = userdata; -} - void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), void *userdata) { @@ -2012,7 +1999,8 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; } - case PACKET_ID_MESSAGE: { + case PACKET_ID_MESSAGE: + case PACKET_ID_ACTION: { const uint8_t *message_id = data; if (data_length == 0) @@ -2025,30 +2013,10 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) uint8_t message_terminated[message_length + 1]; memcpy(message_terminated, message, message_length); message_terminated[message_length] = 0; + uint8_t type = packet_id - PACKET_ID_MESSAGE; if (m->friend_message) - (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); - - break; - } - - case PACKET_ID_ACTION: { - const uint8_t *message_id = data; - - if (data_length == 0) - break; - - const uint8_t *action = data; - uint16_t action_length = data_length; - - /* Make sure the NULL terminator is present. */ - uint8_t action_terminated[action_length + 1]; - memcpy(action_terminated, action, action_length); - action_terminated[action_length] = 0; - - if (m->friend_action) - (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); - + (*m->friend_message)(m, i, type, message_terminated, message_length, m->friend_message_userdata); break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 827a3298..d1a2ed9b 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -37,6 +37,11 @@ #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 @@ -46,7 +51,7 @@ #define PACKET_ID_USERSTATUS 50 #define PACKET_ID_TYPING 51 #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 @@ -101,6 +106,7 @@ enum { FAERR_NOMEM = -8 }; + /* Default start timeout in seconds between friend requests. */ #define FRIENDREQUEST_TIMEOUT 5; @@ -241,10 +247,8 @@ 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, uint32_t, const uint8_t *, size_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, uint32_t, const uint8_t *, size_t, void *); - void *friend_action_userdata; void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); void *friend_namechange_userdata; void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); @@ -363,29 +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 -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. * * the value in message_id will be passed to your read_receipt callback when the other receives the message. */ -int m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, uint32_t *message_id); +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 -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 0 if success. - * - * the value in message_id will be passed to your read_receipt callback when the other receives the message. - */ -int m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length, uint32_t *message_id); /* Set the name and name_length of a friend. * name must be a string of maximum MAX_NAME_LENGTH length. @@ -492,16 +487,10 @@ void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const void *), void *userdata); /* Set the function that will be executed when a message from a friend is received. - * Function format is: function(uint32_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, uint32_t, const uint8_t *, size_t, void *), - void *userdata); - -/* Set the function that will be executed when an action from a friend is received. - * Function format is: function(uint32_t friendnumber, uint8_t * action, uint32_t length) - */ -void m_callback_action(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_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(uint32_t friendnumber, uint8_t *newname, size_t length) diff --git a/toxcore/tox.c b/toxcore/tox.c index 04218ef2..a5141652 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -791,11 +791,15 @@ static void set_message_error(int ret, TOX_ERR_FRIEND_SEND_MESSAGE *error) case -4: SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ); break; + + case -5: + /* can't happen */ + break; } } -uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, - TOX_ERR_FRIEND_SEND_MESSAGE *error) +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, + size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error) { if (!message) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL); @@ -809,26 +813,7 @@ uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, const uint8_t Messenger *m = tox; uint32_t message_id = 0; - set_message_error(m_sendmessage(m, friend_number, message, length, &message_id), error); - return message_id; -} - -uint32_t tox_friend_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, - TOX_ERR_FRIEND_SEND_MESSAGE *error) -{ - if (!action) { - SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL); - return 0; - } - - if (!length) { - SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY); - return 0; - } - - Messenger *m = tox; - uint32_t message_id = 0; - set_message_error(m_sendaction(m, friend_number, action, length, &message_id), error); + set_message_error(m_send_message_generic(m, friend_number, type, message, length, &message_id), error); return message_id; } @@ -850,12 +835,6 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void m_callback_friendmessage(m, function, user_data); } -void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void *user_data) -{ - Messenger *m = tox; - m_callback_action(m, function, user_data); -} - bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) { if (!hash || !data) { diff --git a/toxcore/tox.h b/toxcore/tox.h index 29eb126a..c9be93a0 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -296,6 +296,21 @@ typedef enum TOX_USER_STATUS { TOX_USER_STATUS_INVALID } TOX_USER_STATUS; +/** + * Represents message types for friend messages and group chat + * messages. + */ +typedef enum TOX_MESSAGE_TYPE { + /** + * Normal text message. Similar to PRIVMSG on IRC. + */ + TOX_MESSAGE_TYPE_MESSAGE, + /** + * A message describing an user action. This is similar to /me (CTCP ACTION) + * on IRC. + */ + TOX_MESSAGE_TYPE_ACTION +} TOX_MESSAGE_TYPE; /******************************************************************************* * @@ -1274,6 +1289,8 @@ typedef enum TOX_ERR_FRIEND_SEND_MESSAGE { * This function creates a chat message packet and pushes it into the send * queue. * + * Type corresponds to the message type, for a list of valid types see TOX_MESSAGE_TYPE. + * * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages * must be split by the client and sent as separate messages. Other clients can * then reassemble the fragments. Messages may not be empty. @@ -1285,24 +1302,8 @@ typedef enum TOX_ERR_FRIEND_SEND_MESSAGE { * incremented by 1 each time a message is sent. If UINT32_MAX messages were * sent, the next message ID is 0. */ -uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, - TOX_ERR_FRIEND_SEND_MESSAGE *error); - - -/** - * Send an action to an online friend. - * - * This is similar to /me (CTCP ACTION) on IRC. - * - * Message ID space is shared between tox_send_message and tox_send_action. This - * means that sending a message will cause the next message ID from sending an - * action will be incremented. - * - * @see tox_friend_send_message for more details. - */ -uint32_t tox_friend_send_action(Tox *tox, uint32_t friend_number, const uint8_t *action, size_t length, - TOX_ERR_FRIEND_SEND_MESSAGE *error); - +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, + size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error); /** * The function type for the `read_receipt` callback. @@ -1336,16 +1337,11 @@ void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *func * The function type for the `friend_request` callback. * * @param public_key The Public Key of the user who sent the friend request. - * @param time_delta A delta in seconds between when the message was composed - * and when it is being transmitted. For messages that are sent immediately, - * it will be 0. If a message was written and couldn't be sent immediately - * (due to a connection failure, for example), the time_delta is an - * approximation of when it was composed. * @param message The message they sent along with the request. * @param length The size of the message byte array. */ -typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, /*uint32_t time_delta, */const uint8_t *message, - size_t length, void *user_data); +typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, + void *user_data); /** * Set the callback for the `friend_request` event. Pass NULL to unset. @@ -1359,13 +1355,11 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void * The function type for the `friend_message` callback. * * @param friend_number The friend number of the friend who sent the message. - * @param time_delta Time between composition and sending. + * @param type The message type, for a list of valid types see TOX_MESSAGE_TYPE. * @param message The message data they sent. * @param length The size of the message byte array. - * - * @see tox_friend_request_cb for more information on time_delta. */ -typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */const uint8_t *message, +typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data); /** @@ -1376,28 +1370,6 @@ typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, /*uint32_t void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data); -/** - * The function type for the `friend_action` callback. - * - * @param friend_number The friend number of the friend who sent the action. - * @param time_delta Time between composition and sending. - * @param action The action message data they sent. - * @param length The size of the action byte array. - * - * @see tox_friend_request_cb for more information on time_delta. - */ -typedef void tox_friend_action_cb(Tox *tox, uint32_t friend_number, /*uint32_t time_delta, */const uint8_t *action, - size_t length, void *user_data); - -/** - * Set the callback for the `friend_action` event. Pass NULL to unset. - * - * This event is triggered when an action from a friend is received. - */ -void tox_callback_friend_action(Tox *tox, tox_friend_action_cb *function, void *user_data); - - - /******************************************************************************* * * :: File transmission: common between sending and receiving From dc60d98ff1adba20957543db68706477d4fd1581 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Mar 2015 15:47:09 -0400 Subject: [PATCH 089/101] Removed TOX_USER_STATUS_INVALID. --- toxcore/tox.c | 2 +- toxcore/tox.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/toxcore/tox.c b/toxcore/tox.c index a5141652..f547c402 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -702,7 +702,7 @@ TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TO if (ret == USERSTATUS_INVALID) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); - return TOX_USER_STATUS_INVALID; + return TOX_USER_STATUS_BUSY + 1; } SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); diff --git a/toxcore/tox.h b/toxcore/tox.h index c9be93a0..0df75976 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -289,11 +289,7 @@ typedef enum TOX_USER_STATUS { * User is busy. Signals to other clients that this client does not * currently wish to communicate. */ - TOX_USER_STATUS_BUSY, - /** - * Invalid status used when function returns an error. - */ - TOX_USER_STATUS_INVALID + TOX_USER_STATUS_BUSY } TOX_USER_STATUS; /** From e0bd6ef4e0e79804e36ae86b4f08f19c2ce93700 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 18 Mar 2015 17:14:57 -0400 Subject: [PATCH 090/101] Renamed TOX_MESSAGE_TYPE_MESSAGE to TOX_MESSAGE_TYPE_NORMAL. --- auto_tests/tox_test.c | 6 +++--- testing/nTox.c | 4 ++-- testing/tox_shell.c | 2 +- toxcore/tox.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 100e5748..3883cb85 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -39,7 +39,7 @@ void print_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const u if (*((uint32_t *)userdata) != 974536) return; - if (type != TOX_MESSAGE_TYPE_MESSAGE) { + if (type != TOX_MESSAGE_TYPE_NORMAL) { ck_abort_msg("Bad type"); } @@ -401,9 +401,9 @@ START_TEST(test_few_clients) uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1]; memset(msgs, 'G', sizeof(msgs)); TOX_ERR_FRIEND_SEND_MESSAGE errm; - tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_MESSAGE, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &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_MESSAGE, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); + 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) { diff --git a/testing/nTox.c b/testing/nTox.c index 6b3bfd0d..3cb88edc 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -395,7 +395,7 @@ void line_eval(Tox *m, char *line) int num = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { - if (tox_friend_send_message(m, num, TOX_MESSAGE_TYPE_MESSAGE, (uint8_t *) *posi + 1, strlen(*posi + 1), NULL) < 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); @@ -607,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_friend_send_message(m, friendnumber, TOX_MESSAGE_TYPE_MESSAGE, (uint8_t *)line, strlen(line), NULL); + 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]; diff --git a/testing/tox_shell.c b/testing/tox_shell.c index 64a0517d..23fa320a 100644 --- a/testing/tox_shell.c +++ b/testing/tox_shell.c @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) if (ret <= 0) break; - tox_friend_send_message(tox, num, TOX_MESSAGE_TYPE_MESSAGE, buf, ret, 0); + tox_friend_send_message(tox, num, TOX_MESSAGE_TYPE_NORMAL, buf, ret, 0); } tox_iterate(tox); diff --git a/toxcore/tox.h b/toxcore/tox.h index eec41fc7..f880f71c 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -300,7 +300,7 @@ typedef enum TOX_MESSAGE_TYPE { /** * Normal text message. Similar to PRIVMSG on IRC. */ - TOX_MESSAGE_TYPE_MESSAGE, + TOX_MESSAGE_TYPE_NORMAL, /** * A message describing an user action. This is similar to /me (CTCP ACTION) * on IRC. From d8da9bf7097192f20338ae5c7e34c40405f4f1d1 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 18 Mar 2015 17:19:26 -0500 Subject: [PATCH 091/101] callback_file_request_chunk -> callback_file_chunk_request A couple of minor reasons, combined warrant a PR imo: a) fileChunkRequested is a better signal name than fileRequestChunkReceived, and I don't want to break consistency by reordering words for just this signal b) "request chunk" is parsed by English speakers as a verb-object combination, implying sending the request, not receiving, whereas "chunk requested" is parsed (more correctly) as an adjective-noun combo (in particular, request is a noun not a verb), and thus reads far more like "hey heads up we just got a request" For instance some tests/testing code had some callbacks to *receive* chunk requests, and they were called "tox_file_request_chunk"... to receive a chunk, not request it. Now they're called "tox_file_chunk_request". So yeah... --- auto_tests/tox_test.c | 4 ++-- testing/nTox.c | 4 ++-- testing/tox_sync.c | 4 ++-- toxcore/tox.c | 2 +- toxcore/tox.h | 14 +++++++------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 3883cb85..662c0da5 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -184,7 +184,7 @@ void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t sending_num; _Bool file_sending_done; -void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, +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) @@ -555,7 +555,7 @@ START_TEST(test_few_clients) long long unsigned int 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_request_chunk(tox2, tox_file_request_chunk, &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; diff --git a/testing/nTox.c b/testing/nTox.c index 3cb88edc..f5e860dc 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -121,7 +121,7 @@ typedef struct { File_Sender file_senders[NUM_FILE_SENDERS]; uint8_t numfilesenders; -void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, +void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, void *user_data) { unsigned int i; @@ -1289,7 +1289,7 @@ int main(int argc, char *argv[]) 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_request_chunk(m, tox_file_request_chunk, 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); diff --git a/testing/tox_sync.c b/testing/tox_sync.c index 9fc67b46..e1f54873 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -53,7 +53,7 @@ File_t file_senders[NUM_FILE_SENDERS]; File_t file_recv[NUM_FILE_SENDERS]; uint8_t numfilesenders; -void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, +void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, void *user_data) { unsigned int i; @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) 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_request_chunk(tox, tox_file_request_chunk, 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]); diff --git a/toxcore/tox.c b/toxcore/tox.c index 73007c72..44845138 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1051,7 +1051,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, return 0; } -void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *function, void *user_data) +void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function, void *user_data) { Messenger *m = tox; callback_file_reqchunk(m, function, user_data); diff --git a/toxcore/tox.h b/toxcore/tox.h index f880f71c..6d55b3df 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1621,7 +1621,7 @@ typedef enum TOX_ERR_FILE_SEND { * data of unknown size. * * File transmission occurs in chunks, which are requested through the - * `file_request_chunk` event. + * `file_chunk_request` event. * * When a friend goes offline, all file transfers associated with the friend are * purged from core. @@ -1633,7 +1633,7 @@ typedef enum TOX_ERR_FILE_SEND { * - If the file size was increased * - and sending mode was streaming (file_size = 0), the behaviour will be as * expected. - * - and sending mode was file (file_size != 0), the file_request_chunk + * - and sending mode was file (file_size != 0), the file_chunk_request * callback will receive length = 0 when Core thinks the file transfer has * finished. If the client remembers the file size as it was when sending * the request, it will terminate the transfer normally. If the client @@ -1713,7 +1713,7 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { /** * Send a chunk of file data to a friend. * - * This function is called in response to the `file_request_chunk` callback. The + * This function is called in response to the `file_chunk_request` callback. The * length parameter should be equal to the one received though the callback. * If it is zero, the transfer is assumed complete. For files with known size, * Core will know that the transfer is complete after the last byte has been @@ -1728,7 +1728,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, /** - * The function type for the `file_request_chunk` callback. + * The function type for the `file_chunk_request` callback. * * If the length parameter is 0, the file transfer is finished, and the client's * resources associated with the file number should be released. After a call @@ -1751,13 +1751,13 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, * @param position The file or stream position from which to continue reading. * @param length The number of bytes requested for the current chunk. */ -typedef void tox_file_request_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, +typedef void tox_file_chunk_request_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, void *user_data); /** - * Set the callback for the `file_request_chunk` event. Pass NULL to unset. + * Set the callback for the `file_chunk_request` event. Pass NULL to unset. */ -void tox_callback_file_request_chunk(Tox *tox, tox_file_request_chunk_cb *function, void *user_data); +void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function, void *user_data); /******************************************************************************* From 2b2c9f37a61d677ecca47c88bb993d1d4f88e3ee Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 19 Mar 2015 18:02:46 -0400 Subject: [PATCH 092/101] Fixed group audio issues when getting an old audio packet. --- toxav/group.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/toxav/group.c b/toxav/group.c index 3c09878a..ee556d29 100644 --- a/toxav/group.c +++ b/toxav/group.c @@ -26,6 +26,7 @@ #include "../toxcore/logger.h" #define GROUP_JBUF_SIZE 6 +#define GROUP_JBUF_DEAD_SECONDS 4 typedef struct { uint16_t sequnum; @@ -39,6 +40,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 +92,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 +116,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; } From 8c18dd42a7c24f65d847a99a5147c8922e25fd85 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 19 Mar 2015 18:17:27 -0400 Subject: [PATCH 093/101] Fix build warning. --- toxav/group.c | 1 + 1 file changed, 1 insertion(+) diff --git a/toxav/group.c b/toxav/group.c index ee556d29..817ee6e6 100644 --- a/toxav/group.c +++ b/toxav/group.c @@ -23,6 +23,7 @@ #endif #include "group.h" +#include "../toxcore/util.h" #include "../toxcore/logger.h" #define GROUP_JBUF_SIZE 6 From b1ec15717526679c6d107e3a5a4b2bf08c26b650 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 20 Mar 2015 20:12:07 -0400 Subject: [PATCH 094/101] For file transfers UINT64_MAX is now used as the size for streaming transfers instead of 0. For avatar transfers file size 0 now means that the client has no avatar set. Added a test for streaming transfers. --- auto_tests/tox_test.c | 62 +++++++++++++++++++++++++++++++++++++++++++ toxcore/Messenger.c | 30 +++++++++------------ toxcore/tox.h | 11 +++++--- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 662c0da5..29b91bb2 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -182,6 +182,8 @@ void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, 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, @@ -204,6 +206,15 @@ void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_numb 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); @@ -552,6 +563,7 @@ START_TEST(test_few_clients) 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_recv_chunk(tox3, write_file, &to_compare); tox_callback_file_recv_control(tox2, file_print_control, &to_compare); @@ -598,6 +610,56 @@ 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) { + break; + } else { + ck_abort_msg("Something went wrong in file transfer %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, 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("test_few_clients succeeded, took %llu seconds\n", time(NULL) - cur_time); tox_kill(tox1); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ffebdd29..57e9c172 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1282,7 +1282,7 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin if (ft->status != FILESTATUS_NOT_ACCEPTED) return -5; - if (ft->size && position > ft->size) { + if (position > ft->size) { return -6; } @@ -1356,14 +1356,12 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin if (length > MAX_FILE_DATA_SIZE) return -5; - if (ft->size) { - if (ft->size - ft->transferred < length) { - return -5; - } + if (ft->size - ft->transferred < length) { + return -5; + } - if (length != MAX_FILE_DATA_SIZE && (ft->transferred + length) != ft->size) { - return -5; - } + if (ft->size != UINT64_MAX && length != MAX_FILE_DATA_SIZE && (ft->transferred + length) != ft->size) { + return -5; } if (position != ft->transferred) { @@ -1471,14 +1469,12 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) uint16_t length = MAX_FILE_DATA_SIZE; - if (ft->size) { - if (ft->size == ft->requested) { - break; - } + if (ft->size == ft->requested) { + break; + } - if (ft->size - ft->requested < length) { - length = ft->size - ft->requested; - } + if (ft->size - ft->requested < length) { + length = ft->size - ft->requested; } ++ft->slots_allocated; @@ -1586,7 +1582,7 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv memcpy(&position, data, sizeof(position)); net_to_host((uint8_t *) &position, sizeof(position)); - if (ft->size && position > ft->size) { + if (position > ft->size) { return -1; } @@ -2117,7 +2113,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) ft->transferred += file_data_length; - if ((ft->size && ft->transferred >= ft->size) || file_data_length != MAX_FILE_DATA_SIZE) { + if (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE) { file_data_length = 0; file_data = NULL; position = ft->transferred; diff --git a/toxcore/tox.h b/toxcore/tox.h index 6d55b3df..5a8d6ab2 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1395,6 +1395,9 @@ enum TOX_FILE_KIND { * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar * transfer if it matches. + * + * When file_size is set to 0 in the transfer request it means that the client has no + * avatar. */ TOX_FILE_KIND_AVATAR }; @@ -1631,9 +1634,9 @@ typedef enum TOX_ERR_FILE_SEND { * was modified and how the client determines the file size. * * - If the file size was increased - * - and sending mode was streaming (file_size = 0), the behaviour will be as + * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour will be as * expected. - * - and sending mode was file (file_size != 0), the file_chunk_request + * - and sending mode was file (file_size != UINT64_MAX), the file_chunk_request * callback will receive length = 0 when Core thinks the file transfer has * finished. If the client remembers the file size as it was when sending * the request, it will terminate the transfer normally. If the client @@ -1654,7 +1657,7 @@ typedef enum TOX_ERR_FILE_SEND { * @param friend_number The friend number of the friend the file send request * should be sent to. * @param kind The meaning of the file to be sent. - * @param file_size Size in bytes of the file the client wants to send, 0 if + * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if * unknown or streaming. * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to * uniquely identify file transfers across core restarts. If NULL, a random one will @@ -1804,7 +1807,7 @@ void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_dat * * If position is equal to file_size (received in the file_receive callback) * when the transfer finishes, the file was received completely. Otherwise, if - * file_size was 0, streaming ended successfully when length is 0. + * file_size was UINT64_MAX, streaming ended successfully when length is 0. * * @param friend_number The friend number of the friend who is sending the file. * @param file_number The friend-specific file number the data received is From f2a017c055a8670d3bdbea2610455b45261a334e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 20 Mar 2015 21:15:44 -0400 Subject: [PATCH 095/101] Allow sending of file transfer requests with length 0 but don't allocate any file number for them in core. These can be used to tell friends we don't have an avatar set or to unset a set avatar. --- auto_tests/tox_test.c | 4 ++++ toxcore/Messenger.c | 53 +++++++++++++++++++++++++++---------------- toxcore/Messenger.h | 2 +- toxcore/tox.c | 4 ++++ toxcore/tox.h | 12 +++++++++- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 29b91bb2..66193035 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -202,6 +202,10 @@ void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_numb } if (length == 0) { + if (file_sending_done) { + ck_abort_msg("File sending already done."); + } + file_sending_done = 1; return; } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 57e9c172..ac3c2752 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1091,7 +1091,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). - * + * return -5 if succesfully sent file send request with filesize 0. */ 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) @@ -1115,18 +1115,22 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) return -4; - struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; - ft->status = FILESTATUS_NOT_ACCEPTED; - ft->size = filesize; - ft->transferred = 0; - ft->requested = 0; - ft->slots_allocated = 0; - ft->paused = FILE_PAUSE_NOT; - memcpy(ft->id, file_id, FILE_ID_LENGTH); + /* Only init file if filesize isn't 0. */ + if (filesize) { + struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->requested = 0; + ft->slots_allocated = 0; + ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, file_id, FILE_ID_LENGTH); - ++m->friendlist[friendnumber].num_sending_files; - - return i; + ++m->friendlist[friendnumber].num_sending_files; + return i; + } else { + return -5; + } } int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, @@ -2044,11 +2048,23 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) net_to_host((uint8_t *) &filesize, sizeof(filesize)); struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; - ft->status = FILESTATUS_NOT_ACCEPTED; - ft->size = filesize; - ft->transferred = 0; - ft->paused = FILE_PAUSE_NOT; - memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); + if (ft->status != FILESTATUS_NONE) + break; + + uint32_t real_filenumber = UINT32_MAX; + + if (filesize) { + /* Don't */ + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); + + real_filenumber = filenumber; + real_filenumber += 1; + real_filenumber <<= 16; + } uint8_t filename_terminated[filename_length + 1]; uint8_t *filename = NULL; @@ -2060,9 +2076,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) filename = filename_terminated; } - uint32_t real_filenumber = filenumber; - real_filenumber += 1; - real_filenumber <<= 16; if (m->file_sendrequest) (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index d1a2ed9b..21b474f6 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -618,7 +618,7 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). - * + * return -5 if succesfully sent file send request with filesize 0. */ 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); diff --git a/toxcore/tox.c b/toxcore/tox.c index 44845138..f17eb758 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1000,6 +1000,10 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t case -4: SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED); return UINT32_MAX; + + case -5: + SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK_ZERO_LENGTH); + return UINT32_MAX; } /* can't happen */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 5a8d6ab2..0953daee 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1610,7 +1610,12 @@ typedef enum TOX_ERR_FILE_SEND { * Too many ongoing transfers. The maximum number of concurrent file transfers * is 256 per friend per direction (sending and receiving). */ - TOX_ERR_FILE_SEND_TOO_MANY + TOX_ERR_FILE_SEND_TOO_MANY, + /** + * A file request packet was successfully sent to the friend however since it was zero + * length, no file number was allocated for the file transfer. + */ + TOX_ERR_FILE_SEND_OK_ZERO_LENGTH } TOX_ERR_FILE_SEND; /** @@ -1629,6 +1634,9 @@ typedef enum TOX_ERR_FILE_SEND { * When a friend goes offline, all file transfers associated with the friend are * purged from core. * + * if file_size is 0, this function will not allocate a file transfer in core and so + * will not return a valid file number however it will send a file request packet. + * * If the file contents change during a transfer, the behaviour is unspecified * in general. What will actually happen depends on the mode in which the file * was modified and how the client determines the file size. @@ -1779,6 +1787,8 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *functi * control command before any other control commands. It can be accepted by * sending TOX_FILE_CONTROL_RESUME. * + * If file_size is zero, the file_number is invalid and should be ignored. + * * @param friend_number The friend number of the friend who is sending the file * transfer request. * @param file_number The friend-specific file number the data received is From 8c2347222a1f5ecb19c20a8dfcefbeff66fcb848 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 21 Mar 2015 08:35:31 -0400 Subject: [PATCH 096/101] Transfers with filelength == 0 now behave exactly like transfers of every other size (except streaming of course). --- auto_tests/tox_test.c | 82 ++++++++++++++++++++++++++++++++++++------- toxcore/Messenger.c | 62 +++++++++++++++----------------- toxcore/Messenger.h | 2 +- toxcore/tox.c | 4 --- toxcore/tox.h | 12 +------ 5 files changed, 101 insertions(+), 61 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 66193035..e614ea8f 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -145,16 +145,21 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui } file_size = filesize; - sending_pos = size_recv = 1337; - TOX_ERR_FILE_SEEK err_s; + if (filesize) { + sending_pos = size_recv = 1337; - if (!tox_file_send_seek(tox, friend_number, file_number, 1337, &err_s)) { - ck_abort_msg("tox_file_send_seek error"); + TOX_ERR_FILE_SEEK err_s; + + if (!tox_file_send_seek(tox, friend_number, file_number, 1337, &err_s)) { + ck_abort_msg("tox_file_send_seek error"); + } + + ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_send_seek wrong error"); + } else { + sending_pos = size_recv = 0; } - ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_send_seek wrong error"); - TOX_ERR_FILE_CONTROL error; if (tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) { @@ -163,6 +168,8 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui ck_abort_msg("tox_file_send_control failed. %i", error); } + TOX_ERR_FILE_SEEK err_s; + if (tox_file_send_seek(tox, friend_number, file_number, 1234, &err_s)) { ck_abort_msg("tox_file_send_seek no error"); } @@ -593,11 +600,13 @@ START_TEST(test_few_clients) tox_iterate(tox3); if (file_sending_done) { - if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv) { + 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 %llu %llu %llu", sendf_ok, file_recv, - totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, totalf_size, size_recv, sending_pos); + 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); } } @@ -644,11 +653,12 @@ START_TEST(test_few_clients) if (file_sending_done) { if (sendf_ok && file_recv && m_send_reached && totalf_size == file_size && size_recv == max_sending - && sending_pos == size_recv) { + && 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 %llu", sendf_ok, file_recv, - m_send_reached, totalf_size == file_size, size_recv == max_sending, sending_pos == size_recv, totalf_size, file_size, + 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); } } @@ -664,6 +674,54 @@ START_TEST(test_few_clients) } } + 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); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ac3c2752..265ff80b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1091,7 +1091,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). - * return -5 if succesfully sent file send request with filesize 0. + * */ 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) @@ -1115,22 +1115,18 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) return -4; - /* Only init file if filesize isn't 0. */ - if (filesize) { - struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; - ft->status = FILESTATUS_NOT_ACCEPTED; - ft->size = filesize; - ft->transferred = 0; - ft->requested = 0; - ft->slots_allocated = 0; - ft->paused = FILE_PAUSE_NOT; - memcpy(ft->id, file_id, FILE_ID_LENGTH); + struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->requested = 0; + ft->slots_allocated = 0; + ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, file_id, FILE_ID_LENGTH); - ++m->friendlist[friendnumber].num_sending_files; - return i; - } else { - return -5; - } + ++m->friendlist[friendnumber].num_sending_files; + + return i; } int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, @@ -1473,6 +1469,12 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) uint16_t length = MAX_FILE_DATA_SIZE; + if (ft->size == 0) { + /* Send 0 data to friend if file is 0 length. */ + file_data(m, friendnumber, i, 0, 0, 0); + break; + } + if (ft->size == ft->requested) { break; } @@ -2051,20 +2053,11 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) if (ft->status != FILESTATUS_NONE) break; - uint32_t real_filenumber = UINT32_MAX; - - if (filesize) { - /* Don't */ - ft->status = FILESTATUS_NOT_ACCEPTED; - ft->size = filesize; - ft->transferred = 0; - ft->paused = FILE_PAUSE_NOT; - memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); - - real_filenumber = filenumber; - real_filenumber += 1; - real_filenumber <<= 16; - } + ft->status = FILESTATUS_NOT_ACCEPTED; + ft->size = filesize; + ft->transferred = 0; + ft->paused = FILE_PAUSE_NOT; + memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); uint8_t filename_terminated[filename_length + 1]; uint8_t *filename = NULL; @@ -2076,6 +2069,9 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) filename = filename_terminated; } + uint32_t real_filenumber = filenumber; + real_filenumber += 1; + real_filenumber <<= 16; if (m->file_sendrequest) (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, @@ -2099,13 +2095,13 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_FILE_DATA: { - if (data_length <= 1) + if (data_length < 1) break; uint8_t filenumber = data[0]; struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; - if (ft->status == FILESTATUS_NONE) + if (ft->status != FILESTATUS_TRANSFERRING) break; uint64_t position = ft->transferred; @@ -2126,7 +2122,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) ft->transferred += file_data_length; - if (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE) { + if (file_data_length && (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE)) { file_data_length = 0; file_data = NULL; position = ft->transferred; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 21b474f6..d1a2ed9b 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -618,7 +618,7 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u * return -2 if filename length invalid. * return -3 if no more file sending slots left. * return -4 if could not send packet (friend offline). - * return -5 if succesfully sent file send request with filesize 0. + * */ 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); diff --git a/toxcore/tox.c b/toxcore/tox.c index f17eb758..44845138 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1000,10 +1000,6 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t case -4: SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED); return UINT32_MAX; - - case -5: - SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK_ZERO_LENGTH); - return UINT32_MAX; } /* can't happen */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 0953daee..5a8d6ab2 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1610,12 +1610,7 @@ typedef enum TOX_ERR_FILE_SEND { * Too many ongoing transfers. The maximum number of concurrent file transfers * is 256 per friend per direction (sending and receiving). */ - TOX_ERR_FILE_SEND_TOO_MANY, - /** - * A file request packet was successfully sent to the friend however since it was zero - * length, no file number was allocated for the file transfer. - */ - TOX_ERR_FILE_SEND_OK_ZERO_LENGTH + TOX_ERR_FILE_SEND_TOO_MANY } TOX_ERR_FILE_SEND; /** @@ -1634,9 +1629,6 @@ typedef enum TOX_ERR_FILE_SEND { * When a friend goes offline, all file transfers associated with the friend are * purged from core. * - * if file_size is 0, this function will not allocate a file transfer in core and so - * will not return a valid file number however it will send a file request packet. - * * If the file contents change during a transfer, the behaviour is unspecified * in general. What will actually happen depends on the mode in which the file * was modified and how the client determines the file size. @@ -1787,8 +1779,6 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *functi * control command before any other control commands. It can be accepted by * sending TOX_FILE_CONTROL_RESUME. * - * If file_size is zero, the file_number is invalid and should be ignored. - * * @param friend_number The friend number of the friend who is sending the file * transfer request. * @param file_number The friend-specific file number the data received is From b0983104d501d6906af56c5dc669e98541306f69 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 21 Mar 2015 08:58:54 -0400 Subject: [PATCH 097/101] Renamed tox_file_send_control to tox_file_control. Renamed tox_file_send_seek to tox_file_seek. --- auto_tests/tox_test.c | 16 ++++++++-------- testing/nTox.c | 4 ++-- testing/tox_sync.c | 8 ++++---- toxcore/tox.c | 8 ++++---- toxcore/tox.h | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index e614ea8f..0dab2e69 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -151,30 +151,30 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui TOX_ERR_FILE_SEEK err_s; - if (!tox_file_send_seek(tox, friend_number, file_number, 1337, &err_s)) { - ck_abort_msg("tox_file_send_seek error"); + 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_send_seek wrong 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_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) { + if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) { ++file_accepted; } else { - ck_abort_msg("tox_file_send_control failed. %i", error); + ck_abort_msg("tox_file_control failed. %i", error); } TOX_ERR_FILE_SEEK err_s; - if (tox_file_send_seek(tox, friend_number, file_number, 1234, &err_s)) { - ck_abort_msg("tox_file_send_seek no error"); + 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_send_seek wrong error"); + ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error"); } uint32_t sendf_ok; diff --git a/testing/nTox.c b/testing/nTox.c index f5e860dc..77f812b5 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1133,7 +1133,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, { if (type != TOX_FILE_KIND_DATA) { new_lines("Refused invalid file type."); - tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -1141,7 +1141,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, 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(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { + 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 diff --git a/testing/tox_sync.c b/testing/tox_sync.c index e1f54873..be1fe32d 100644 --- a/testing/tox_sync.c +++ b/testing/tox_sync.c @@ -129,7 +129,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, { if (type != TOX_FILE_KIND_DATA) { printf("Refused invalid file type."); - tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -151,7 +151,7 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, if (tempfile != 0) { fclose(tempfile); - tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } @@ -159,11 +159,11 @@ void file_request_accept(Tox *tox, uint32_t friend_number, uint32_t file_number, file_recv[file_index].file = fopen(fullpath, "wb"); if (file_recv[file_index].file == 0) { - tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); + tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_CANCEL, 0); return; } - if (tox_file_send_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { + if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, 0)) { printf("Accepted file transfer. (file: %s)\n", fullpath); } diff --git a/toxcore/tox.c b/toxcore/tox.c index 44845138..191dd428 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -845,8 +845,8 @@ bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) return 1; } -bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, - TOX_ERR_FILE_CONTROL *error) +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, + TOX_ERR_FILE_CONTROL *error) { Messenger *m = tox; int ret = file_control(m, friend_number, file_number, control); @@ -894,8 +894,8 @@ bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_numbe return 0; } -bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, - TOX_ERR_FILE_SEEK *error) +bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + TOX_ERR_FILE_SEEK *error) { Messenger *m = tox; int ret = file_seek(m, friend_number, file_number, position); diff --git a/toxcore/tox.h b/toxcore/tox.h index 5a8d6ab2..f7fc9a62 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1489,8 +1489,8 @@ typedef enum TOX_ERR_FILE_CONTROL { * * @return true on success. */ -bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, - TOX_ERR_FILE_CONTROL *error); +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, + TOX_ERR_FILE_CONTROL *error); /** @@ -1555,8 +1555,8 @@ typedef enum TOX_ERR_FILE_SEEK { * @param file_number The friend-specific identifier for the file transfer. * @param position The position that the file should be seeked to. */ -bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, - TOX_ERR_FILE_SEEK *error); +bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, + TOX_ERR_FILE_SEEK *error); typedef enum TOX_ERR_FILE_GET { TOX_ERR_FILE_GET_OK, From 79cbad38d0408f03be37abdb63c1736d49dd1929 Mon Sep 17 00:00:00 2001 From: Anurag Agarwal Date: Sun, 22 Mar 2015 20:18:47 +0530 Subject: [PATCH 098/101] Fixes #1296 --- toxcore/tox.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index f7fc9a62..39df905a 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1128,7 +1128,7 @@ typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, cons /** * Set the callback for the `friend_status_message` event. Pass NULL to unset. * - * This event is triggered when a friend changes their name. + * This event is triggered when a friend changes their status message. */ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data); From 19d2f4db982d03fbaa2dadbf6c1aff4f33727537 Mon Sep 17 00:00:00 2001 From: Anurag Agarwal Date: Sun, 22 Mar 2015 20:26:21 +0530 Subject: [PATCH 099/101] Fixes #1297 --- toxcore/tox.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toxcore/tox.h b/toxcore/tox.h index 39df905a..a828325f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1724,6 +1724,9 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK { * chunk to terminate. For streams, core will know that the transfer is finished * if a chunk with length less than the length requested in the callback is sent. * + * @param friend_number The friend number of the receiving friend for this file. + * @param file_number The file transfer identifier returned by tox_file_send. + * @param position The file or stream position from which to continue reading. * @return true on success. */ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, From 4c664fd07a66d03e58845edef2c4cd8dc04b51ba Mon Sep 17 00:00:00 2001 From: Anurag Agarwal Date: Sun, 22 Mar 2015 20:36:44 +0530 Subject: [PATCH 100/101] Fixes #1298 --- toxcore/tox.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/toxcore/tox.h b/toxcore/tox.h index a828325f..e674fc65 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -1776,6 +1776,9 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *functi /** * The function type for the `file_receive` callback. * + * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename should generally just be + * a file name, not a path with directory names. + * * The client should acquire resources to be associated with the file transfer. * Incoming file transfers start in the PAUSED state. After this callback * returns, a transfer can be rejected by sending a TOX_FILE_CONTROL_CANCEL @@ -1786,6 +1789,10 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *functi * transfer request. * @param file_number The friend-specific file number the data received is * associated with. + * @param kind The meaning of the file to be sent. + * @param file_size Size in bytes of the file about to be received from the client, + * UINT64_MAX if unknown or streaming. + * @param filename_length Size in bytes of the filename. */ typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data); From 47d1c1db7eecd71e0d68ba9c8c4be9c25a079125 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 23 Mar 2015 16:56:56 -0400 Subject: [PATCH 101/101] Added some more checks for file packets. --- toxcore/Messenger.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 265ff80b..57ec652c 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2040,9 +2040,17 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; uint8_t filenumber = data[0]; + + if (filenumber >= MAX_CONCURRENT_FILE_PIPES) + break; + uint64_t filesize; uint32_t file_type; uint16_t filename_length = data_length - head_length; + + if (filename_length > MAX_FILENAME_LENGTH) + break; + memcpy(&file_type, data + 1, sizeof(file_type)); file_type = ntohl(file_type); @@ -2088,6 +2096,9 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) uint8_t filenumber = data[1]; uint8_t control_type = data[2]; + if (filenumber >= MAX_CONCURRENT_FILE_PIPES) + break; + if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) break; @@ -2099,6 +2110,10 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; uint8_t filenumber = data[0]; + + if (filenumber >= MAX_CONCURRENT_FILE_PIPES) + break; + struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; if (ft->status != FILESTATUS_TRANSFERRING)