From eac0d435f35db468435fa596a3b00b593d6bf3e9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 13 Feb 2015 16:18:02 -0500 Subject: [PATCH] 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 }