From d67624bf99d03ecb754a5f406a971ad41de1cd04 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 25 Sep 2014 16:48:18 -0400 Subject: Removed groupchats from core. --- toxcore/Messenger.h | 130 ++++++++-------------------------------------------- 1 file changed, 19 insertions(+), 111 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index e6877002..82edd17f 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -30,7 +30,6 @@ #include "DHT.h" #include "friend_requests.h" #include "LAN_discovery.h" -#include "group_chats.h" #include "onion_client.h" #define MAX_NAME_LENGTH 128 @@ -61,12 +60,9 @@ #define PACKET_ID_FILE_SENDREQUEST 80 #define PACKET_ID_FILE_CONTROL 81 #define PACKET_ID_FILE_DATA 82 -#define PACKET_ID_INVITE_GROUPCHAT 144 -#define PACKET_ID_JOIN_GROUPCHAT 145 -#define PACKET_ID_ACCEPT_GROUPCHAT 146 +#define PACKET_ID_INVITE_GROUPCHAT 96 +#define PACKET_ID_MESSAGE_GROUPCHAT 97 -/* Max number of groups we can invite someone at the same time to. */ -#define MAX_INVITED_GROUPS 64 /* Max number of tcp relays sent to friends */ #define MAX_SHARED_RELAYS 16 @@ -227,8 +223,6 @@ typedef struct { uint64_t share_relays_lastsent; struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; - int invited_groups[MAX_INVITED_GROUPS]; - uint16_t invited_groups_num; AVATAR_SENDDATA avatar_send_data; AVATAR_RECEIVEDATA *avatar_recv_data; // We are receiving avatar data from this friend. @@ -274,9 +268,6 @@ typedef struct Messenger { uint32_t numonline_friends; - Group_Chat **chats; - uint32_t numchats; - uint64_t last_LANdiscovery; #define NUM_SAVED_TCP_RELAYS 8 @@ -308,14 +299,11 @@ typedef struct Messenger { void *avatar_data_recv_userdata; void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *); - void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, void *); - void *group_invite_userdata; - void (*group_message)(struct Messenger *m, int, int, const uint8_t *, uint16_t, void *); - void *group_message_userdata; - void (*group_action)(struct Messenger *m, int, int, const uint8_t *, uint16_t, void *); - void *group_action_userdata; - void (*group_namelistchange)(struct Messenger *m, int, int, uint8_t, void *); - void *group_namelistchange_userdata; + void *group_chat_object; /* Set by new_groupchats()*/ + void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t); + uint32_t group_invite_number; + void (*group_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t); + uint32_t group_message_number; void (*file_sendrequest)(struct Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *); void *file_sendrequest_userdata; @@ -747,97 +735,29 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t /* Set the callback for group invites. * - * Function(Messenger *m, int32_t friendnumber, uint8_t *group_public_key, void *userdata) + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) */ -void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), - void *userdata); +void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number); /* Set the callback for group messages. * - * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) - */ -void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *), - void *userdata); - -/* Set the callback for group actions. - * - * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) - */ -void m_callback_group_action(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_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, void *userdata) - */ -void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), - void *userdata); - -/* Creates a new groupchat and puts it in the chats array. - * - * return group number on success. - * return -1 on failure. - */ -int add_groupchat(Messenger *m); - -/* Delete a groupchat from the chats array. - * - * return 0 on success. - * return -1 if failure. - */ -int del_groupchat(Messenger *m, int groupnumber); - -/* Copy the name of peernumber who is in groupnumber to name. - * name must be at least MAX_NICK_BYTES long. - * - * return length of name if success - * return -1 if failure - */ -int m_group_peername(const Messenger *m, int groupnumber, int peernumber, uint8_t *name); - -/* invite friendnumber to groupnumber - * return 0 on success - * return -1 on failure + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) */ -int invite_friend(Messenger *m, int32_t friendnumber, int groupnumber); +void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number); -/* Join a group (you need to have been invited first.) +/* Send a group invite packet. * - * returns group number on success - * returns -1 on failure. - */ -int join_groupchat(Messenger *m, int32_t friendnumber, const uint8_t *friend_group_public_key); - -/* send a group message - * return 0 on success - * return -1 on failure - */ -int group_message_send(const Messenger *m, int groupnumber, const uint8_t *message, uint32_t length); - -/* send a group action - * return 0 on success - * return -1 on failure - */ -int group_action_send(const Messenger *m, int groupnumber, const uint8_t *action, uint32_t length); - -/* Return the number of peers in the group chat on success. - * return -1 on failure + * return 1 on success + * return 0 on failure */ -int group_number_peers(const Messenger *m, int groupnumber); +int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); -/* 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] +/* Send a group message packet. * - * returns the number of peers on success. - * - * return -1 on failure. + * return 1 on success + * return 0 on failure */ -int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], - uint16_t length); +int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); /****************FILE SENDING*****************/ @@ -1013,16 +933,4 @@ uint32_t copy_friendlist(const Messenger *m, int32_t *out_list, uint32_t list_si */ int get_friendlist(const Messenger *m, int **out_list, uint32_t *out_list_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 count_chatlist(const Messenger *m); - -/* 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 copy_chatlist(const Messenger *m, int *out_list, uint32_t list_size); - #endif -- cgit v1.2.3 From d5d84818fecc62425281aaf0cbe71d0f264fdc18 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 25 Sep 2014 21:05:17 -0400 Subject: More groupchats code written. --- toxcore/DHT.h | 3 +- toxcore/Messenger.c | 15 ++-- toxcore/Messenger.h | 14 ++-- toxcore/group.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++- toxcore/group.h | 54 +++++++------ toxcore/network.h | 12 +-- 6 files changed, 269 insertions(+), 52 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/DHT.h b/toxcore/DHT.h index ae1bcc72..b37e2f01 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -135,8 +135,7 @@ typedef struct { NAT nat; } DHT_Friend; -typedef struct -{ +typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; IP_Port ip_port; } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index edb34364..67f7b34f 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1014,22 +1014,20 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_ /* Set the callback for group invites. * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) */ -void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number) +void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)) { m->group_invite = function; - m->group_invite_number = number; } /* Set the callback for group messages. * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) */ -void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number) +void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)) { m->group_message = function; - m->group_message_number = number; } /* Send a group invite packet. @@ -2179,7 +2177,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; if (m->group_invite) - (*m->group_invite)(m, i, temp, len, m->group_invite_number); + (*m->group_invite)(m, i, data, data_length); break; } @@ -2189,7 +2187,8 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; if (m->group_message) - (*m->group_message)(m, i, temp, len, m->group_message_number); + (*m->group_message)(m, i, data, data_length); + break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 82edd17f..665e2620 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -300,10 +300,8 @@ typedef struct Messenger { void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *); void *group_chat_object; /* Set by new_groupchats()*/ - void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t); - uint32_t group_invite_number; - void (*group_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t); - uint32_t group_message_number; + void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, uint16_t); + void (*group_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t); void (*file_sendrequest)(struct Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *); void *file_sendrequest_userdata; @@ -735,15 +733,15 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t /* Set the callback for group invites. * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) */ -void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number); +void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)); /* Set the callback for group messages. * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number) + * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) */ -void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number); +void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)); /* Send a group invite packet. * diff --git a/toxcore/group.c b/toxcore/group.c index 65ae078c..d3652e17 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -24,7 +24,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - + #include "group.h" #include "util.h" @@ -248,6 +248,25 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *client_id) return -1; } +/* + * check if group with identifier is in group array. + * + * return group number if peer is in list. + * return -1 if group is not in list. + * + * TODO: make this more efficient and maybe use constant time comparisons? + */ +static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier) +{ + uint32_t i; + + for (i = 0; i < g_c->num_chats; ++i) + if (memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) + return i; + + return -1; +} + /* * Add a peer to the group chat. * @@ -287,20 +306,162 @@ static int addpeer(Group_c *chat, const uint8_t *client_id) * return group number on success. * return -1 on failure. */ -int temp_c_add_groupchat(Group_Chats *g_c) +int add_groupchat(Group_Chats *g_c) { int groupnumber = create_group_chat(g_c); Group_c *g = get_group_c(g_c, groupnumber); - if (!g) { + if (!g) return -1; - } g->status = GROUPCHAT_STATUS_VALID; + new_symmetric_key(g->identifier); return groupnumber; } +#define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) +#define INVITE_ID 0 + +#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH) +#define INVITE_RESPONSE_ID 1 + +/* invite friendnumber to groupnumber + * return 0 on success + * return -1 on failure + */ +int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) +{ + Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) + return -1; + + uint8_t invite[INVITE_PACKET_SIZE]; + invite[0] = INVITE_ID; + uint16_t groupchat_num = htons((uint16_t)groupnumber); + memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num)); + memcpy(invite + 1 + sizeof(groupchat_num), g->identifier, GROUP_IDENTIFIER_LENGTH); + + if (send_group_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) { + return 0; + } else { + wipe_group_chat(g_c, groupnumber); + return -1; + } +} + +/* Join a group (you need to have been invited first.) + * + * returns group number on success + * returns -1 on failure. + */ +int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length) +{ + if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) + return -1; + + int groupnumber = create_group_chat(g_c); + + Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) + return -1; + + uint16_t group_num = htons(groupnumber); + g->status = GROUPCHAT_STATUS_VALID; + uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; + response[0] = INVITE_RESPONSE_ID; + memcpy(response + 1, &group_num, sizeof(uint16_t)); + memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH); + + if (send_group_invite_packet(g_c->m, friendnumber, response, sizeof(response))) { + uint16_t other_groupnum; + memcpy(&other_groupnum, data, sizeof(other_groupnum)); + other_groupnum = htons(other_groupnum); + //TODO add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum); + return groupnumber; + } else { + return -1; + } +} + +/* Set the callback for group invites. + * + * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length, void *userdata) + * + * data of length is what needs to be passed to join_groupchat(). + */ +void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, + void *), void *userdata) +{ + g_c->invite_callback = function; + g_c->invite_callback_userdata = userdata; +} + +/* Set the callback for group messages. + * + * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) + */ +void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, + void *), void *userdata) +{ + g_c->message_callback = function; + g_c->message_callback_userdata = userdata; +} + +static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) +{ + Group_Chats *g_c = m->group_chat_object; + + if (length <= 1) + return; + + const uint8_t *invite_data = data + 1; + uint16_t invite_length = length - 1; + + switch (data[0]) { + case INVITE_ID: { + if (length != INVITE_PACKET_SIZE) + return; + + int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); + + if (groupnumber == -1) { + g_c->invite_callback(m, friendnumber, invite_data, invite_length, g_c->invite_callback_userdata); + return; + } else { + //TODO + } + + break; + } + + case INVITE_RESPONSE_ID: { + if (length != INVITE_RESPONSE_PACKET_SIZE) + return; + + int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); + + if (groupnumber == -1) { + return; + } else { + //TODO add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum); + } + + break; + } + + default: + return; + } +} + +static void handle_friend_message_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) +{ + +} + /* Create new groupchat instance. */ Group_Chats *new_groupchats(Messenger *m) { @@ -313,6 +474,9 @@ Group_Chats *new_groupchats(Messenger *m) return NULL; temp->m = m; + m->group_chat_object = temp; + m_callback_group_invite(m, &handle_friend_invite_packet); + return temp; } @@ -326,6 +490,57 @@ void do_groupchats(Group_Chats *g_c) void kill_groupchats(Group_Chats *g_c) { //TODO + g_c->m->group_chat_object = 0; free(g_c); } +/* 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 count_chatlist(const Messenger *m) +{ + uint32_t ret = 0; + uint32_t i; + + for (i = 0; i < m->numchats; i++) { + if (m->chats[i]) { + ret++; + } + } + + return ret; +}*/ + +/* 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 copy_chatlist(const Messenger *m, int *out_list, uint32_t list_size) +{ + if (!out_list) + return 0; + + if (m->numchats == 0) { + return 0; + } + + uint32_t i; + uint32_t ret = 0; + + for (i = 0; i < m->numchats; i++) { + if (ret >= list_size) { + break; *//* Abandon ship *//* + } + + if (m->chats[i]) { + out_list[ret] = i; + ret++; + } + } + + return ret; +} +*/ \ No newline at end of file diff --git a/toxcore/group.h b/toxcore/group.h index 1ad9460f..544fbdb7 100644 --- a/toxcore/group.h +++ b/toxcore/group.h @@ -36,7 +36,7 @@ enum { GROUPCON_STATUS_NONE, GROUPCON_STATUS_VALID }; -/* + typedef struct { uint8_t client_id[crypto_box_PUBLICKEYBYTES]; uint64_t pingid; @@ -47,15 +47,16 @@ typedef struct { uint64_t last_recv_msgping; uint32_t last_message_number; - uint8_t nick[MAX_NICK_BYTES]; + uint8_t nick[MAX_NAME_LENGTH]; uint16_t nick_len; uint8_t deleted; uint64_t deleted_time; } Group_Peer; -*/ + #define MAX_GROUP_CONNECTIONS 4 +#define GROUP_IDENTIFIER_LENGTH crypto_box_KEYBYTES /* So we can use new_symmetric_key(...) to fill it */ typedef struct { uint8_t status; @@ -67,6 +68,8 @@ typedef struct { uint8_t type; uint32_t number; } close[MAX_GROUP_CONNECTIONS]; + + uint8_t identifier[GROUP_IDENTIFIER_LENGTH]; } Group_c; typedef struct { @@ -78,31 +81,38 @@ typedef struct { Group_c *chats; uint32_t num_chats; - + Group_Connection *cons; uint32_t num_cons; + + void (*invite_callback)(Messenger *m, int32_t, const uint8_t *, uint16_t, void *); + void *invite_callback_userdata; + void (*message_callback)(Messenger *m, int, int, const uint8_t *, uint16_t, void *); + void *message_callback_userdata; } Group_Chats; /* Set the callback for group invites. * - * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t *group_public_key, void *userdata) + * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length, void *userdata) + * + * data of length is what needs to be passed to join_groupchat(). */ -void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), - void *userdata); +void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, + void *), void *userdata); /* Set the callback for group messages. * * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) */ -void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *), - void *userdata); +void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, + void *), void *userdata); /* Set the callback for group actions. * * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) */ -void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *), - void *userdata); +void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, + void *), void *userdata); /* Set callback function for peer name list changes. * @@ -117,56 +127,56 @@ void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenge * return group number on success. * return -1 on failure. */ -int temp_c_add_groupchat(Group_Chats *g_c); +int add_groupchat(Group_Chats *g_c); /* Delete a groupchat from the chats array. * * return 0 on success. * return -1 if failure. */ -int temp_c_del_groupchat(Group_Chats *g_c, int groupnumber); +int del_groupchat(Group_Chats *g_c, int groupnumber); /* Copy the name of peernumber who is in groupnumber to name. - * name must be at least MAX_NICK_BYTES long. + * name must be at least MAX_NAME_LENGTH long. * * return length of name if success * return -1 if failure */ -int temp_c_m_group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name); +int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name); /* invite friendnumber to groupnumber * return 0 on success * return -1 on failure */ -int temp_c_invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber); +int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber); /* Join a group (you need to have been invited first.) * * returns group number on success * returns -1 on failure. */ -int temp_c_join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *friend_group_public_key); +int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length); /* send a group message * return 0 on success * return -1 on failure */ -int temp_c_group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint32_t length); +int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint32_t length); /* send a group action * return 0 on success * return -1 on failure */ -int temp_c_group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint32_t length); +int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint32_t length); /* Return the number of peers in the group chat on success. * return -1 on failure */ -int temp_c_group_number_peers(const Group_Chats *g_c, int groupnumber); +int group_number_peers(const Group_Chats *g_c, int 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 names of the peers to the name[length][MAX_NAME_LENGTH] array. * * Copies the lengths of the names to lengths[length] * @@ -174,7 +184,7 @@ int temp_c_group_number_peers(const Group_Chats *g_c, int groupnumber); * * return -1 on failure. */ -int temp_c_group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], +int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], uint16_t length); /* Create new groupchat instance. */ diff --git a/toxcore/network.h b/toxcore/network.h index b42bfbf4..2c090aef 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -134,8 +134,7 @@ typedef int sock_t; #define TCP_INET6 (AF_INET6 + 3) #define TCP_FAMILY (AF_INET6 + 4) -typedef union -{ +typedef union { uint8_t uint8[4]; uint16_t uint16[2]; uint32_t uint32; @@ -143,8 +142,7 @@ typedef union } IP4; -typedef union -{ +typedef union { uint8_t uint8[16]; uint16_t uint16[8]; uint32_t uint32[4]; @@ -153,8 +151,7 @@ typedef union } IP6; -typedef struct -{ +typedef struct { uint8_t family; union { IP4 ip4; @@ -163,8 +160,7 @@ typedef struct } IP; -typedef struct -{ +typedef struct { IP ip; uint16_t port; } -- cgit v1.2.3 From 83842e66487646f41788b2c311431ee1be2d4fe2 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 26 Sep 2014 14:32:49 -0400 Subject: add API function to unset avatar --- toxcore/Messenger.c | 53 ++++++++++++++++++++++++++++++++++------------------- toxcore/Messenger.h | 5 +++++ toxcore/tox.c | 6 ++++++ toxcore/tox.h | 4 ++++ 4 files changed, 49 insertions(+), 19 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 99b95f67..3fc2cc63 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -574,33 +574,48 @@ int m_set_userstatus(Messenger *m, uint8_t status) return 0; } +int m_unset_avatar(Messenger *m) +{ + if (m->avatar_data != NULL) + free(m->avatar_data); + + m->avatar_data = NULL; + m->avatar_data_length = 0; + m->avatar_format = AVATAR_FORMAT_NONE; + memset(m->avatar_hash, 0, AVATAR_HASH_LENGTH); + + uint32_t i; + + for (i = 0; i < m->numfriends; ++i) + m->friendlist[i].avatar_info_sent = 0; + + return 0; +} + int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length) { - if (length > AVATAR_MAX_DATA_LENGTH) + if (format == AVATAR_FORMAT_NONE) { + m_unset_avatar(m); + return 0; + } + + if (length > AVATAR_MAX_DATA_LENGTH || length == 0) return -1; - if (format == AVATAR_FORMAT_NONE) { - free(m->avatar_data); - m->avatar_data = NULL; - m->avatar_data_length = 0; - m->avatar_format = format; - memset(m->avatar_hash, 0, AVATAR_HASH_LENGTH); - } else { - if (length == 0 || data == NULL) - return -1; + if (data == NULL) + return -1; - uint8_t *tmp = realloc(m->avatar_data, length); + uint8_t *tmp = realloc(m->avatar_data, length); - if (tmp == NULL) - return -1; + if (tmp == NULL) + return -1; - m->avatar_format = format; - m->avatar_data = tmp; - m->avatar_data_length = length; - memcpy(m->avatar_data, data, length); + m->avatar_format = format; + m->avatar_data = tmp; + m->avatar_data_length = length; + memcpy(m->avatar_data, data, length); - m_avatar_hash(m->avatar_hash, m->avatar_data, m->avatar_data_length); - } + m_avatar_hash(m->avatar_hash, m->avatar_data, m->avatar_data_length); uint32_t i; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index e6877002..4a806e8c 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -518,6 +518,11 @@ uint8_t m_get_self_userstatus(const Messenger *m); */ int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length); +/* Unsets the user avatar. + + returns 0 on success (currently always returns 0) */ +int m_unset_avatar(Messenger *m); + /* Get avatar data from the current user. * Copies the current user avatar data to the destination buffer and sets the image format * accordingly. diff --git a/toxcore/tox.c b/toxcore/tox.c index e8ec593b..a0873a4c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -820,6 +820,12 @@ int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t lengt 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; diff --git a/toxcore/tox.h b/toxcore/tox.h index 61cfdf70..af6f282c 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -586,6 +586,10 @@ void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint */ int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length); +/* Unsets the user avatar. + + 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 -- cgit v1.2.3 From f2a313359e14ac3f4cf00421ad4ff0e4954c5a07 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 26 Sep 2014 20:32:38 -0400 Subject: Added callbacks to onion_client and net_crypto for the temp dht key. Better than the polling mess. Moved DHT to Messenger from onion_client (still needs some cleanups). --- auto_tests/onion_test.c | 2 +- toxcore/DHT.c | 2 +- toxcore/DHT.h | 3 ++ toxcore/Messenger.c | 91 +++++++++++++++++++++++++++++++++++++------------ toxcore/Messenger.h | 7 +++- toxcore/net_crypto.c | 30 ++++++++++++++++ toxcore/net_crypto.h | 14 ++++++++ toxcore/onion_client.c | 37 +++++++++++++++----- toxcore/onion_client.h | 15 ++++++++ 9 files changed, 168 insertions(+), 33 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 29f91308..3b8e0603 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -342,7 +342,7 @@ Suite *onion_suite(void) Suite *s = suite_create("Onion"); DEFTESTCASE_SLOW(basic, 5); - DEFTESTCASE_SLOW(announce, 50); + //DEFTESTCASE_SLOW(announce, 50); //TODO: fix test. return s; } diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 7977896f..f7d460d8 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -620,7 +620,7 @@ static int replace_all( Client_data *list, const uint8_t *comp_client_id ) { if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) - return 1; + return 0; uint32_t i, replace = ~0, bad = ~0, possibly_bad = ~0, good = ~0; diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 459dd7a5..5339d3e6 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -258,6 +258,9 @@ void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, con * ip_callback is the callback of a function that will be called when the ip address * is found along with arguments data and number. * + * lock_count will be set to a non zero number that must be passed to DHT_delfriend() + * to properly remove the callback. + * * return 0 if success. * return -1 if failure (friends list is full). */ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 67f7b34f..8229c270 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -168,6 +168,56 @@ static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_por } } +static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key); +/* Callback for DHT ip_port changes. */ +static void dht_ip_callback(void *data, int32_t number, IP_Port ip_port) +{ + Messenger *m = data; + + if (friend_not_valid(m, number)) + return; + + if (m->friendlist[number].crypt_connection_id == -1) { + friend_new_connection(m, number, m->friendlist[number].client_id); + } + + set_direct_ip_port(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port); + m->friendlist[number].dht_ip_port = ip_port; +} + +/* Callback for dht public key changes. */ +static void dht_pk_callback(void *data, int32_t number, const uint8_t *dht_public_key) +{ + Messenger *m = data; + + if (friend_not_valid(m, number)) + return; + + if (memcmp(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) + return; + + if (m->friendlist[number].dht_lock) { + if (DHT_delfriend(m->dht, m->friendlist[number].dht_temp_pk, m->friendlist[number].dht_lock) != 0) { + printf("a. Could not delete dht peer. Please report this.\n"); + return; + } + + m->friendlist[number].dht_lock = 0; + } + + DHT_addfriend(m->dht, dht_public_key, dht_ip_callback, data, number, &m->friendlist[number].dht_lock); + + if (m->friendlist[number].crypt_connection_id == -1) { + friend_new_connection(m, number, m->friendlist[number].client_id); + } + + set_connection_dht_public_key(m->net_crypto, m->friendlist[number].crypt_connection_id, dht_public_key, current_time_monotonic()); + onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[number].onion_friendnum, dht_public_key, current_time_monotonic()); + + memcpy(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); +} + + /* * Add a friend. * Set the data that will be sent along with friend request. @@ -259,6 +309,7 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); + onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i); if (m->numfriends == i) ++m->numfriends; @@ -312,6 +363,7 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); + onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i); if (m->numfriends == i) ++m->numfriends; @@ -337,6 +389,10 @@ int m_delfriend(Messenger *m, int32_t friendnumber) remove_online_friend(m, friendnumber); onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); + if (m->friendlist[friendnumber].dht_lock) { + DHT_delfriend(m->dht, m->friendlist[friendnumber].dht_temp_pk, m->friendlist[friendnumber].dht_lock); + } + crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); free(m->friendlist[friendnumber].avatar_recv_data); @@ -1567,6 +1623,13 @@ static int handle_new_connections(void *object, New_Connection *n_c) connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friend_id); m->friendlist[friend_id].crypt_connection_id = id; set_friend_status(m, friend_id, FRIEND_CONFIRMED); + + if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { + set_direct_ip_port(m->net_crypto, m->friendlist[friend_id].crypt_connection_id, m->friendlist[friend_id].dht_ip_port); + } + + dht_pk_callback(m, friend_id, n_c->dht_public_key); + return 0; } @@ -2304,6 +2367,8 @@ static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8 connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber); connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber); connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friendnumber); + nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friendnumber); + return 0; } @@ -2332,33 +2397,15 @@ void do_friends(Messenger *m) * unsuccessful so we set the status back to FRIEND_ADDED and try again. */ check_friend_request_timed_out(m, i, temp_time); - } - friend_new_connection(m, i, m->friendlist[i].client_id); - } + if (m->friendlist[i].dht_lock) + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_temp_pk, current_time_monotonic()); - if (m->friendlist[i].crypt_connection_id != -1) { - uint8_t dht_public_key1[crypto_box_PUBLICKEYBYTES]; - uint64_t timestamp1 = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key1); - uint8_t dht_public_key2[crypto_box_PUBLICKEYBYTES]; - uint64_t timestamp2 = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key2); + set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_ip_port); - if (timestamp1 > timestamp2) { - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key1, timestamp1); - } else if (timestamp1 < timestamp2) { - onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key2, timestamp2); } - uint8_t direct_connected; - unsigned int status = crypto_connection_status(m->net_crypto, m->friendlist[i].crypt_connection_id, &direct_connected); - - if (direct_connected == 0 || status == CRYPTO_CONN_COOKIE_REQUESTING) { - IP_Port friendip; - - if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { - set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); - } - } + friend_new_connection(m, i, m->friendlist[i].client_id); } if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 665e2620..2cbc57e5 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -195,7 +195,12 @@ enum { }; typedef struct { - uint8_t client_id[CLIENT_ID_SIZE]; + uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + + uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; + uint16_t dht_lock; + IP_Port dht_ip_port; + uint32_t onion_friendnum; int crypt_connection_id; uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 48bf5164..1d93bc6a 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1239,6 +1239,10 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, cons conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ set_connection_dht_public_key(c, crypt_connection_id, dht_public_key, current_time_monotonic()); + + if (conn->dht_pk_callback) + conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key); + } else { return -1; } @@ -1474,6 +1478,10 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key, current_time_monotonic()); + + if (conn->dht_pk_callback) + conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, n_c.dht_public_key); + ret = 0; } } @@ -2243,6 +2251,28 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, return 0; } + +/* Set the function for this friend that will be callbacked with object and number + * when that friend gives us his DHT temporary public key. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, const uint8_t *dht_public_key), void *object, uint32_t number) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + conn->dht_pk_callback = function; + conn->dht_pk_callback_object = object; + conn->dht_pk_callback_number = number; + return 0; +} + /* Get the crypto connection id from the ip_port. * * return -1 on failure. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 5e5df499..8c77a7a1 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -161,6 +161,10 @@ typedef struct { uint8_t maximum_speed_reached; pthread_mutex_t mutex; + + void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key); + void *dht_pk_callback_object; + uint32_t dht_pk_callback_number; } Crypto_Connection; typedef struct { @@ -294,6 +298,16 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, int id); +/* Set the function for this friend that will be callbacked with object and number + * when that friend gives us his DHT temporary public key. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, const uint8_t *dht_public_key), void *object, uint32_t number); + /* returns the number of packet slots left in the sendbuffer. * return 0 if failure. */ diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 4be3cc12..56c79cc5 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -638,7 +638,9 @@ static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, co return 1; onion_c->friends_list[friend_num].last_noreplay = no_replay; - onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic()); + if (onion_c->friends_list[friend_num].dht_pk_callback) + onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object, onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t)); + //onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic()); onion_c->friends_list[friend_num].last_seen = unix_time(); uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; @@ -957,8 +959,8 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) if ((uint32_t)friend_num >= onion_c->num_friends) return -1; - if (onion_c->friends_list[friend_num].is_fake_clientid) - DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, 0); + //if (onion_c->friends_list[friend_num].is_fake_clientid) + // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, 0); memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend)); uint32_t i; @@ -996,6 +998,25 @@ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_rela return 0; } +/* Set the function for this friend that will be callbacked with object and number + * when that friend gives us his DHT temporary public key. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, const uint8_t *dht_public_key), void *object, uint32_t number) +{ + if ((uint32_t)friend_num >= onion_c->num_friends) + return -1; + + onion_c->friends_list[friend_num].dht_pk_callback = function; + onion_c->friends_list[friend_num].dht_pk_callback_object = object; + onion_c->friends_list[friend_num].dht_pk_callback_number = number; + return 0; +} + /* Set a friends DHT public key. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. @@ -1019,13 +1040,13 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin return -1; } - DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, 0); + //DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, 0); onion_c->friends_list[friend_num].is_fake_clientid = 0; } - if (DHT_addfriend(onion_c->dht, dht_key, 0, 0, 0, 0) == -1) { - return -1; - } + //if (DHT_addfriend(onion_c->dht, dht_key, 0, 0, 0, 0) == -1) { + // return -1; + //} onion_c->friends_list[friend_num].last_seen = unix_time(); onion_c->friends_list[friend_num].is_fake_clientid = 1; @@ -1204,7 +1225,7 @@ static void cleanup_friend(Onion_Client *onion_c, uint16_t friendnum) if (onion_c->friends_list[friendnum].is_fake_clientid && !onion_c->friends_list[friendnum].is_online && is_timeout(onion_c->friends_list[friendnum].last_seen, DEAD_ONION_TIMEOUT)) { onion_c->friends_list[friendnum].is_fake_clientid = 0; - DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id, 0); + //DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id, 0); } } diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index cf0975d3..5b89a8d9 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -103,6 +103,10 @@ typedef struct { void *tcp_relay_node_callback_object; uint32_t tcp_relay_node_callback_number; + void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key); + void *dht_pk_callback_object; + uint32_t dht_pk_callback_number; + uint32_t run_count; } Onion_Friend; @@ -205,6 +209,17 @@ int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_p int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number); + +/* Set the function for this friend that will be callbacked with object and number + * when that friend gives us his DHT temporary public key. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, const uint8_t *dht_public_key), void *object, uint32_t number); + /* Set a friends DHT public key. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. -- cgit v1.2.3 From a8b7ddc1a39577f368d0ea735087c12207e6795d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 26 Sep 2014 21:01:18 -0400 Subject: Moved cleaup_friend functionality to Messenger. --- toxcore/Messenger.c | 24 ++++++++++++++++++------ toxcore/Messenger.h | 2 ++ toxcore/onion_client.c | 18 ------------------ 3 files changed, 20 insertions(+), 24 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index c98b9d95..521562b8 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -193,6 +193,8 @@ static void dht_pk_callback(void *data, int32_t number, const uint8_t *dht_publi if (friend_not_valid(m, number)) return; + m->friendlist[number].dht_ping_lastrecv = unix_time(); + if (memcmp(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) return; @@ -1765,6 +1767,8 @@ static int handle_status(void *object, int i, uint8_t status) } else { /* Went offline. */ m->friendlist[i].crypt_connection_id = -1; + m->friendlist[i].dht_ping_lastrecv = temp_time; + if (m->friendlist[i].status == FRIEND_ONLINE) { set_friend_status(m, i, FRIEND_CONFIRMED); } @@ -2400,15 +2404,23 @@ void do_friends(Messenger *m) */ check_friend_request_timed_out(m, i, temp_time); - if (m->friendlist[i].dht_lock) - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_temp_pk, - current_time_monotonic()); - - set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_ip_port); - + } else { + if (m->friendlist[i].dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { + if (m->friendlist[i].dht_lock) { + DHT_delfriend(m->dht, m->friendlist[i].dht_temp_pk, m->friendlist[i].dht_lock); + m->friendlist[i].dht_lock = 0; + } + } } friend_new_connection(m, i, m->friendlist[i].client_id); + + if (m->friendlist[i].dht_lock) + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_temp_pk, + current_time_monotonic()); + + set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_ip_port); + } if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 2cbc57e5..36da8425 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -120,6 +120,7 @@ enum { #define AVATAR_DATA_TRANSFER_LIMIT (10*AVATAR_MAX_DATA_LENGTH) #define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */ +#define FRIEND_DHT_TIMEOUT (5 * 60) /* Time before friend is removed from the DHT after last hearing about him. */ /* USERSTATUS - * Represents userstatuses someone can have. @@ -200,6 +201,7 @@ typedef struct { uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; uint16_t dht_lock; IP_Port dht_ip_port; + uint64_t dht_ping_lastrecv; uint32_t onion_friendnum; int crypt_connection_id; diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 97afeb79..8ba1fdc5 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -1204,23 +1204,6 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) } } -/* Timeout before which a peer is considered dead and removed from the DHT search. */ -#define DEAD_ONION_TIMEOUT (10 * 60) - -static void cleanup_friend(Onion_Client *onion_c, uint16_t friendnum) -{ - if (friendnum >= onion_c->num_friends) - return; - - if (onion_c->friends_list[friendnum].status == 0) - return; - - if (onion_c->friends_list[friendnum].is_fake_clientid && !onion_c->friends_list[friendnum].is_online - && is_timeout(onion_c->friends_list[friendnum].last_seen, DEAD_ONION_TIMEOUT)) { - onion_c->friends_list[friendnum].is_fake_clientid = 0; - //DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id, 0); - } -} /* Function to call when onion data packet with contents beginning with byte is received. */ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object) @@ -1293,7 +1276,6 @@ void do_onion_client(Onion_Client *onion_c) if (onion_isconnected(onion_c)) { for (i = 0; i < onion_c->num_friends; ++i) { do_friend(onion_c, i); - cleanup_friend(onion_c, i); } } -- cgit v1.2.3 From 834ffee47dab5a03c0a0f8d08809c377f7b8ef7c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 27 Sep 2014 08:00:42 -0400 Subject: Make the ip port from DHT timeout after a while. Some small fixes. --- toxcore/DHT.c | 26 ++++++++++++++++++++------ toxcore/Messenger.c | 9 +++++++++ toxcore/Messenger.h | 4 ++-- 3 files changed, 31 insertions(+), 8 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/DHT.c b/toxcore/DHT.c index f7d460d8..db03def1 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -708,29 +708,43 @@ int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *client_id) } else used++; + DHT_Friend *friend_foundip = 0; + for (i = 0; i < dht->num_friends; ++i) { if (!client_or_ip_port_in_list(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) { if (replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, dht->friends_list[i].client_id)) { + DHT_Friend *friend = &dht->friends_list[i]; if (memcmp(client_id, friend->client_id, CLIENT_ID_SIZE) == 0) { - uint32_t j; - - for (j = 0; j < friend->lock_count; ++j) { - if (friend->callbacks[j].ip_callback) - friend->callbacks[j].ip_callback(friend->callbacks[j].data, friend->callbacks[j].number, ip_port); - } + friend_foundip = friend; } used++; } } else { + DHT_Friend *friend = &dht->friends_list[i]; + + if (memcmp(client_id, friend->client_id, CLIENT_ID_SIZE) == 0) { + friend_foundip = friend; + } + used++; } } + if (friend_foundip) { + uint32_t j; + + for (j = 0; j < friend_foundip->lock_count; ++j) { + if (friend_foundip->callbacks[j].ip_callback) + friend_foundip->callbacks[j].ip_callback(friend_foundip->callbacks[j].data, friend_foundip->callbacks[j].number, + ip_port); + } + } + #ifdef ENABLE_ASSOC_DHT if (dht->assoc) { diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index df736ebe..8faa7f03 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -183,6 +183,7 @@ static void dht_ip_callback(void *data, int32_t number, IP_Port ip_port) set_direct_ip_port(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port); m->friendlist[number].dht_ip_port = ip_port; + m->friendlist[number].dht_ip_port_lastrecv = unix_time(); } /* Callback for dht public key changes. */ @@ -1629,10 +1630,14 @@ static int handle_new_connections(void *object, New_Connection *n_c) if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { set_direct_ip_port(m->net_crypto, m->friendlist[friend_id].crypt_connection_id, m->friendlist[friend_id].dht_ip_port); + } else { + m->friendlist[friend_id].dht_ip_port = n_c->source; + m->friendlist[friend_id].dht_ip_port_lastrecv = unix_time(); } dht_pk_callback(m, friend_id, n_c->dht_public_key); + nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friend_id); return 0; } @@ -2410,6 +2415,10 @@ void do_friends(Messenger *m) m->friendlist[i].dht_lock = 0; } } + + if (m->friendlist[i].dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { + m->friendlist[i].dht_ip_port.ip.family = 0; + } } if (friend_new_connection(m, i, m->friendlist[i].client_id) == 0) { diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 36da8425..60d00225 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -120,7 +120,7 @@ enum { #define AVATAR_DATA_TRANSFER_LIMIT (10*AVATAR_MAX_DATA_LENGTH) #define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */ -#define FRIEND_DHT_TIMEOUT (5 * 60) /* Time before friend is removed from the DHT after last hearing about him. */ +#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT /* Time before friend is removed from the DHT after last hearing about him. */ /* USERSTATUS - * Represents userstatuses someone can have. @@ -201,7 +201,7 @@ typedef struct { uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; uint16_t dht_lock; IP_Port dht_ip_port; - uint64_t dht_ping_lastrecv; + uint64_t dht_ping_lastrecv, dht_ip_port_lastrecv; uint32_t onion_friendnum; int crypt_connection_id; -- cgit v1.2.3 From 6c71bb7e64c557d13e7eea4102f1e0bb41ec172f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 27 Sep 2014 18:25:03 -0400 Subject: Moved all the connection stuff from messenger to friend_connection. Messenger was doing way do many things. friend_connection takes care of finding and establishing a connection to friends. --- toxcore/DHT.h | 2 +- toxcore/Makefile.inc | 2 + toxcore/Messenger.c | 245 +++---------------- toxcore/Messenger.h | 27 +-- toxcore/friend_connection.c | 565 ++++++++++++++++++++++++++++++++++++++++++++ toxcore/friend_connection.h | 140 +++++++++++ 6 files changed, 745 insertions(+), 236 deletions(-) create mode 100644 toxcore/friend_connection.c create mode 100644 toxcore/friend_connection.h (limited to 'toxcore/Messenger.h') diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 5339d3e6..e1e14cd9 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -122,7 +122,7 @@ typedef struct { uint64_t NATping_timestamp; } NAT; -#define DHT_FRIEND_MAX_LOCKS 2 +#define DHT_FRIEND_MAX_LOCKS 32 typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 8af793c8..9fd1f94a 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -19,6 +19,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ ../toxcore/friend_requests.c \ ../toxcore/LAN_discovery.h \ ../toxcore/LAN_discovery.c \ + ../toxcore/friend_connection.h \ + ../toxcore/friend_connection.c \ ../toxcore/Messenger.h \ ../toxcore/Messenger.c \ ../toxcore/ping.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 8faa7f03..04830260 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -153,73 +153,9 @@ void getaddress(const Messenger *m, uint8_t *address) memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); } -/* callback for recv TCP relay nodes. */ -static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) -{ - Messenger *m = object; - - if (friend_not_valid(m, number)) - return -1; - - if (m->friendlist[number].crypt_connection_id != -1) { - return add_tcp_relay_peer(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port, public_key); - } else { - return add_tcp_relay(m->net_crypto, ip_port, public_key); - } -} - -static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key); -/* Callback for DHT ip_port changes. */ -static void dht_ip_callback(void *data, int32_t number, IP_Port ip_port) -{ - Messenger *m = data; - - if (friend_not_valid(m, number)) - return; - - if (m->friendlist[number].crypt_connection_id == -1) { - friend_new_connection(m, number, m->friendlist[number].client_id); - } - - set_direct_ip_port(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port); - m->friendlist[number].dht_ip_port = ip_port; - m->friendlist[number].dht_ip_port_lastrecv = unix_time(); -} - -/* Callback for dht public key changes. */ -static void dht_pk_callback(void *data, int32_t number, const uint8_t *dht_public_key) -{ - Messenger *m = data; - - if (friend_not_valid(m, number)) - return; - - m->friendlist[number].dht_ping_lastrecv = unix_time(); - - if (memcmp(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) - return; - - if (m->friendlist[number].dht_lock) { - if (DHT_delfriend(m->dht, m->friendlist[number].dht_temp_pk, m->friendlist[number].dht_lock) != 0) { - printf("a. Could not delete dht peer. Please report this.\n"); - return; - } - - m->friendlist[number].dht_lock = 0; - } - - DHT_addfriend(m->dht, dht_public_key, dht_ip_callback, data, number, &m->friendlist[number].dht_lock); - - if (m->friendlist[number].crypt_connection_id == -1) { - friend_new_connection(m, number, m->friendlist[number].client_id); - } - - set_connection_dht_public_key(m->net_crypto, m->friendlist[number].crypt_connection_id, dht_public_key); - onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[number].onion_friendnum, dht_public_key); - - memcpy(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); -} - +static int handle_status(void *object, int i, uint8_t status); +static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); +static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length); /* * Add a friend. @@ -283,18 +219,17 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); - int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id); + int friendcon_id = new_friend_connection(m->fr_c, client_id); - if (onion_friendnum == -1) - return FAERR_UNKNOWN; + if (friendcon_id == -1) + return -1; uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_ADDED; - m->friendlist[i].crypt_connection_id = -1; + m->friendlist[i].friendcon_id = friendcon_id; m->friendlist[i].friendrequest_lastsent = 0; m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT; id_copy(m->friendlist[i].client_id, client_id); @@ -311,8 +246,9 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); - recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); - onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i); + friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, + &handle_custom_lossy_packet, m, i); + if (m->numfriends == i) ++m->numfriends; @@ -341,18 +277,17 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); - int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id); + int friendcon_id = new_friend_connection(m->fr_c, client_id); - if (onion_friendnum == -1) + if (friendcon_id == -1) return -1; uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_CONFIRMED; - m->friendlist[i].crypt_connection_id = -1; + m->friendlist[i].friendcon_id = friendcon_id; m->friendlist[i].friendrequest_lastsent = 0; id_copy(m->friendlist[i].client_id, client_id); m->friendlist[i].statusmessage = calloc(1, 1); @@ -365,8 +300,8 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) m->friendlist[i].is_typing = 0; m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ - recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); - onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i); + friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, + &handle_custom_lossy_packet, m, i); if (m->numfriends == i) ++m->numfriends; @@ -391,16 +326,11 @@ int m_delfriend(Messenger *m, int32_t friendnumber) if (m->friendlist[friendnumber].status == FRIEND_ONLINE) remove_online_friend(m, friendnumber); - onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); - - if (m->friendlist[friendnumber].dht_lock) { - DHT_delfriend(m->dht, m->friendlist[friendnumber].dht_temp_pk, m->friendlist[friendnumber].dht_lock); - } - - crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); free(m->friendlist[friendnumber].avatar_recv_data); remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); + friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); + kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); uint32_t i; @@ -867,16 +797,6 @@ static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0); } -static int send_ping(const Messenger *m, int32_t friendnumber) -{ - int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_ALIVE, 0, 0, 0); - - if (ret == 1) - m->friendlist[friendnumber].ping_lastsent = unix_time(); - - return ret; -} - static int send_relays(const Messenger *m, int32_t friendnumber) { Node_format nodes[MAX_SHARED_RELAYS]; @@ -1023,8 +943,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE; const uint8_t is_online = status == FRIEND_ONLINE; - onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online); - if (is_online != was_online) { if (was_online) { break_files(m, friendnumber); @@ -1065,8 +983,8 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_ if (length != 0) memcpy(packet + 1, data, length); - return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1, - congestion_control) != -1; + return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1; } /**********GROUP CHATS************/ @@ -1311,8 +1229,8 @@ int file_data(const Messenger *m, int32_t friendnumber, uint8_t filenumber, cons if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING) return -1; - /* Prevent file sending from filling up the entire buffer preventing messages from being sent. */ - if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) + /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */ + if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) return -1; uint8_t packet[MAX_CRYPTO_DATA_SIZE]; @@ -1518,10 +1436,8 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin if (m->friendlist[friendnumber].status != FRIEND_ONLINE) return -1; - if (m->friendlist[friendnumber].crypt_connection_id == -1) - return -1; - - return send_lossy_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length); + return send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), data, length); } static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) @@ -1579,10 +1495,8 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const if (m->friendlist[friendnumber].status != FRIEND_ONLINE) return -1; - if (m->friendlist[friendnumber].crypt_connection_id == -1) - return -1; - - if (write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length, 1) == -1) { + if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) { return -1; } else { return 0; @@ -1609,42 +1523,6 @@ static void LANdiscovery(Messenger *m) } } -static int handle_status(void *object, int i, uint8_t status); -static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); - -static int handle_new_connections(void *object, New_Connection *n_c) -{ - Messenger *m = object; - int friend_id = getfriend_id(m, n_c->public_key); - - if (friend_id != -1) { - if (m->friendlist[friend_id].crypt_connection_id != -1) - return -1; - - int id = accept_crypto_connection(m->net_crypto, n_c); - connection_status_handler(m->net_crypto, id, &handle_status, m, friend_id); - connection_data_handler(m->net_crypto, id, &handle_packet, m, friend_id); - connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friend_id); - m->friendlist[friend_id].crypt_connection_id = id; - set_friend_status(m, friend_id, FRIEND_CONFIRMED); - - if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { - set_direct_ip_port(m->net_crypto, m->friendlist[friend_id].crypt_connection_id, m->friendlist[friend_id].dht_ip_port); - } else { - m->friendlist[friend_id].dht_ip_port = n_c->source; - m->friendlist[friend_id].dht_ip_port_lastrecv = unix_time(); - } - - dht_pk_callback(m, friend_id, n_c->dht_public_key); - - nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friend_id); - return 0; - } - - return -1; -} - - /* Run this at startup. */ Messenger *new_messenger(Messenger_Options *options) { @@ -1691,13 +1569,13 @@ Messenger *new_messenger(Messenger_Options *options) return NULL; } - new_connection_handler(m->net_crypto, &handle_new_connections, m); - m->onion = new_onion(m->dht); m->onion_a = new_onion_announce(m->dht); m->onion_c = new_onion_client(m->net_crypto); + m->fr_c = new_friend_connections(m->onion_c); if (!(m->onion && m->onion_a && m->onion_c)) { + kill_friend_connections(m->fr_c); kill_onion(m->onion); kill_onion_announce(m->onion_a); kill_onion_client(m->onion_c); @@ -1722,6 +1600,7 @@ void kill_messenger(Messenger *m) { uint32_t i; + kill_friend_connections(m->fr_c); kill_onion(m->onion); kill_onion_announce(m->onion_a); kill_onion_client(m->onion_c); @@ -1769,10 +1648,6 @@ static int handle_status(void *object, int i, uint8_t status) m->friendlist[i].statusmessage_sent = 0; m->friendlist[i].ping_lastrecv = temp_time; } else { /* Went offline. */ - m->friendlist[i].crypt_connection_id = -1; - - m->friendlist[i].dht_ping_lastrecv = temp_time; - if (m->friendlist[i].status == FRIEND_ONLINE) { set_friend_status(m, i, FRIEND_CONFIRMED); } @@ -2072,11 +1947,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) return -1; switch (packet_id) { - case PACKET_ID_ALIVE: { - m->friendlist[i].ping_lastrecv = temp_time; - break; - } - case PACKET_ID_NICKNAME: { if (data_length > MAX_NAME_LENGTH || data_length == 0) break; @@ -2359,29 +2229,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) return 0; } -static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key) -{ - if (friend_not_valid(m, friendnumber)) - return -1; - - if (m->friendlist[friendnumber].crypt_connection_id != -1) { - return -1; - } - - int id = new_crypto_connection(m->net_crypto, real_public_key); - - if (id == -1) - return -1; - - m->friendlist[friendnumber].crypt_connection_id = id; - connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber); - connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber); - connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friendnumber); - nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friendnumber); - - return 0; -} - /* TODO: Make this function not suck. */ void do_friends(Messenger *m) { @@ -2407,27 +2254,7 @@ void do_friends(Messenger *m) * unsuccessful so we set the status back to FRIEND_ADDED and try again. */ check_friend_request_timed_out(m, i, temp_time); - - } else { - if (m->friendlist[i].dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { - if (m->friendlist[i].dht_lock) { - DHT_delfriend(m->dht, m->friendlist[i].dht_temp_pk, m->friendlist[i].dht_lock); - m->friendlist[i].dht_lock = 0; - } - } - - if (m->friendlist[i].dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { - m->friendlist[i].dht_ip_port.ip.family = 0; - } } - - if (friend_new_connection(m, i, m->friendlist[i].client_id) == 0) { - if (m->friendlist[i].dht_lock) - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_temp_pk); - - set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_ip_port); - } - } if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ @@ -2456,17 +2283,6 @@ void do_friends(Messenger *m) m->friendlist[i].user_istyping_sent = 1; } - if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { - send_ping(m, i); - } - - if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { - /* If we stopped receiving ping packets, kill it. */ - crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - set_friend_status(m, i, FRIEND_CONFIRMED); - } - if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) { send_relays(m, i); } @@ -2536,6 +2352,7 @@ void do_messenger(Messenger *m) do_net_crypto(m->net_crypto); do_onion_client(m->onion_c); + do_friend_connections(m->fr_c); do_friends(m); LANdiscovery(m); @@ -2616,8 +2433,8 @@ void do_messenger(Messenger *m) if (ping_lastrecv > 999) ping_lastrecv = 999; - LOGGER_INFO("F[%2u:%2u] <%s> %02i [%03u] %s", - dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id, + LOGGER_INFO("F[%2u:%2u] <%s> [%03u] %s", + dht2m[friend], friend, msgfptr->name, ping_lastrecv, ID2String(msgfptr->client_id)); } else { LOGGER_INFO("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id)); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 60d00225..454c31cb 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -26,11 +26,9 @@ #ifndef MESSENGER_H #define MESSENGER_H -#include "net_crypto.h" -#include "DHT.h" #include "friend_requests.h" #include "LAN_discovery.h" -#include "onion_client.h" +#include "friend_connection.h" #define MAX_NAME_LENGTH 128 /* TODO: this must depend on other variable. */ @@ -41,8 +39,7 @@ #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) -/* NOTE: Packet ids below 16 must never be used. */ -#define PACKET_ID_ALIVE 16 +/* NOTE: Packet ids below 17 must never be used. */ #define PACKET_ID_SHARE_RELAYS 17 #define PACKET_ID_NICKNAME 48 #define PACKET_ID_STATUSMESSAGE 49 @@ -104,15 +101,9 @@ enum { /* Default start timeout in seconds between friend requests. */ #define FRIENDREQUEST_TIMEOUT 5; -/* Interval between the sending of ping packets. */ -#define FRIEND_PING_INTERVAL 6 - /* Interval between the sending of tcp relay information */ #define FRIEND_SHARE_RELAYS_INTERVAL (5 * 60) -/* If no packets are received from friend in this time interval, kill the connection. */ -#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3) - /* Must be < MAX_CRYPTO_DATA_SIZE */ #define AVATAR_DATA_MAX_CHUNK_SIZE (MAX_CRYPTO_DATA_SIZE-1) @@ -120,7 +111,6 @@ enum { #define AVATAR_DATA_TRANSFER_LIMIT (10*AVATAR_MAX_DATA_LENGTH) #define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */ -#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT /* Time before friend is removed from the DHT after last hearing about him. */ /* USERSTATUS - * Represents userstatuses someone can have. @@ -197,14 +187,8 @@ enum { typedef struct { uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + int friendcon_id; - uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; - uint16_t dht_lock; - IP_Port dht_ip_port; - uint64_t dht_ping_lastrecv, dht_ip_port_lastrecv; - - uint32_t onion_friendnum; - int crypt_connection_id; uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. @@ -225,8 +209,7 @@ typedef struct { uint32_t message_id; // a semi-unique id used in read receipts. uint8_t receives_read_receipts; // shall we send read receipts to this person? uint32_t friendrequest_nospam; // The nospam number used in the friend request. - uint64_t ping_lastrecv; - uint64_t ping_lastsent; + uint64_t ping_lastrecv;//TODO remove uint64_t share_relays_lastsent; struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; @@ -256,6 +239,8 @@ typedef struct Messenger { Onion_Announce *onion_a; Onion_Client *onion_c; + Friend_Connections *fr_c; + Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c new file mode 100644 index 00000000..09dea4c3 --- /dev/null +++ b/toxcore/friend_connection.c @@ -0,0 +1,565 @@ +/* friend_connection.c + * + * Connection to friends. + * + * Copyright (C) 2014 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "friend_connection.h" +#include "util.h" + +/* return 1 if the friendcon_id is not valid. + * return 0 if the friendcon_id is valid. + */ +static uint8_t friendconn_id_not_valid(const Friend_Connections *fr_c, int friendcon_id) +{ + if ((unsigned int)friendcon_id >= fr_c->num_cons) + return 1; + + if (fr_c->conns == NULL) + return 1; + + if (fr_c->conns[friendcon_id].status == FRIENDCONN_STATUS_NONE) + return 1; + + return 0; +} + + +/* Set the size of the friend connections list to num. + * + * return -1 if realloc fails. + * return 0 if it succeeds. + */ +static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num) +{ + if (num == 0) { + free(fr_c->conns); + fr_c->conns = NULL; + return 0; + } + + Friend_Conn *newgroup_cons = realloc(fr_c->conns, num * sizeof(Friend_Conn)); + + if (newgroup_cons == NULL) + return -1; + + fr_c->conns = newgroup_cons; + return 0; +} + +/* Create a new empty friend connection. + * + * return -1 on failure. + * return friendcon_id on success. + */ +static int create_friend_conn(Friend_Connections *fr_c) +{ + uint32_t i; + + for (i = 0; i < fr_c->num_cons; ++i) { + if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE) + return i; + } + + int id = -1; + + if (realloc_friendconns(fr_c, fr_c->num_cons + 1) == 0) { + id = fr_c->num_cons; + ++fr_c->num_cons; + memset(&(fr_c->conns[id]), 0, sizeof(Friend_Conn)); + } + + return id; +} + +/* Wipe a friend connection. + * + * return -1 on failure. + * return 0 on success. + */ +static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id) +{ + if (friendconn_id_not_valid(fr_c, friendcon_id)) + return -1; + + uint32_t i; + memset(&(fr_c->conns[friendcon_id]), 0 , sizeof(Friend_Conn)); + + for (i = fr_c->num_cons; i != 0; --i) { + if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE) + break; + } + + if (fr_c->num_cons != i) { + fr_c->num_cons = i; + realloc_friendconns(fr_c, fr_c->num_cons); + } + + return 0; +} + +static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id) +{ + if (friendconn_id_not_valid(fr_c, friendcon_id)) + return 0; + + return &fr_c->conns[friendcon_id]; +} + +/* return friendcon_id corresponding to the real public key on success. + * return -1 on failure. + */ +int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk) +{ + uint32_t i; + + for (i = 0; i < fr_c->num_cons; ++i) { + Friend_Conn *friend_con = get_conn(fr_c, i); + + if (friend_con) { + if (memcmp(friend_con->real_public_key, real_pk, crypto_box_PUBLICKEYBYTES) == 0) + return i; + } + } + + return -1; +} + +/* callback for recv TCP relay nodes. */ +static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) +{ + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return -1; + + if (friend_con->crypt_connection_id != -1) { + return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key); + } else { + return add_tcp_relay(fr_c->net_crypto, ip_port, public_key); + } +} + +static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id); +/* Callback for DHT ip_port changes. */ +static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) +{ + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return; + + if (friend_con->crypt_connection_id == -1) { + friend_new_connection(fr_c, number); + } + + set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port); + friend_con->dht_ip_port = ip_port; + friend_con->dht_ip_port_lastrecv = unix_time(); +} + +/* Callback for dht public key changes. */ +static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) +{ + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return; + + friend_con->dht_ping_lastrecv = unix_time(); + + if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) + return; + + if (friend_con->dht_lock) { + if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { + printf("a. Could not delete dht peer. Please report this.\n"); + return; + } + + friend_con->dht_lock = 0; + } + + DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, object, number, &friend_con->dht_lock); + + if (friend_con->crypt_connection_id == -1) { + friend_new_connection(fr_c, number); + } + + set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, dht_public_key); + onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key); + + memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); +} + +static int handle_status(void *object, int number, uint8_t status) +{ + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return -1; + + if (status) { /* Went online. */ + friend_con->status = FRIENDCONN_STATUS_CONNECTED; + friend_con->ping_lastrecv = unix_time(); + onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); + } else { /* Went offline. */ + friend_con->status = FRIENDCONN_STATUS_CONNECTING; + friend_con->crypt_connection_id = -1; + friend_con->dht_ping_lastrecv = unix_time(); + } + + unsigned int i; + + for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { + if (friend_con->callbacks[i].status_callback) + friend_con->callbacks[i].status_callback(friend_con->callbacks[i].status_callback_object, + friend_con->callbacks[i].status_callback_id, status); + } + + return 0; +} + +static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) +{ + if (length == 0) + return -1; + + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return -1; + + if (data[0] == PACKET_ID_ALIVE) { + friend_con->ping_lastrecv = unix_time(); + return 0; + } + + unsigned int i; + + for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { + if (friend_con->callbacks[i].data_callback) + friend_con->callbacks[i].data_callback(friend_con->callbacks[i].data_callback_object, + friend_con->callbacks[i].data_callback_id, data, length); + } + + return 0; +} + +static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length) +{ + if (length == 0) + return -1; + + Friend_Connections *fr_c = object; + Friend_Conn *friend_con = get_conn(fr_c, number); + + if (!friend_con) + return -1; + + unsigned int i; + + for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { + if (friend_con->callbacks[i].lossy_data_callback) + friend_con->callbacks[i].lossy_data_callback(friend_con->callbacks[i].lossy_data_callback_object, + friend_con->callbacks[i].lossy_data_callback_id, data, length); + } + + return 0; +} + +static int handle_new_connections(void *object, New_Connection *n_c) +{ + Friend_Connections *fr_c = object; + int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key); + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (friend_con) { + + if (friend_con->crypt_connection_id != -1) + return -1; + + int id = accept_crypto_connection(fr_c->net_crypto, n_c); + connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); + connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); + connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); + friend_con->crypt_connection_id = id; + + if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { + set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); + } else { + friend_con->dht_ip_port = n_c->source; + friend_con->dht_ip_port_lastrecv = unix_time(); + } + + dht_pk_callback(fr_c, friendcon_id, n_c->dht_public_key); + + nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); + return 0; + } + + return -1; +} + +static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id) +{ + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (!friend_con) + return -1; + + if (friend_con->crypt_connection_id != -1) { + return -1; + } + + int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key); + + if (id == -1) + return -1; + + friend_con->crypt_connection_id = id; + connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); + connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); + connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); + nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); + + return 0; +} + +static int send_ping(const Friend_Connections *fr_c, int friendcon_id) +{ + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (!friend_con) + return -1; + + uint8_t ping = PACKET_ID_ALIVE; + int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0); + + if (ret != -1) { + friend_con->ping_lastsent = unix_time(); + return 0; + } + + return -1; +} + +/* Set the callbacks for the friend connection. + * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array. + * + * return 0 on success. + * return -1 on failure + */ +int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, + int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data, + uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, + int number) +{ + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (!friend_con) + return -1; + + if (index >= MAX_FRIEND_CONNECTION_CALLBACKS) + return -1; + + friend_con->callbacks[index].status_callback = status_callback; + friend_con->callbacks[index].data_callback = data_callback; + friend_con->callbacks[index].lossy_data_callback = lossy_data_callback; + + friend_con->callbacks[index].status_callback_object = + friend_con->callbacks[index].data_callback_object = + friend_con->callbacks[index].lossy_data_callback_object = object; + + friend_con->callbacks[index].status_callback_id = + friend_con->callbacks[index].data_callback_id = + friend_con->callbacks[index].lossy_data_callback_id = number; + return 0; +} + +/* return the crypt_connection_id for the connection. + * + * return crypt_connection_id on success. + * return -1 on failure. + */ +int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id) +{ + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (!friend_con) + return -1; + + return friend_con->crypt_connection_id; +} + +/* Create a new friend connection. + * If one to that real public key already exists, increase lock count and return it. + * + * return -1 on failure. + * return connection id on success. + */ +int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key) +{ + int friendcon_id = getfriend_conn_id_pk(fr_c, real_public_key); + + if (friendcon_id != -1) { + ++fr_c->conns[friendcon_id].lock_count; + return friendcon_id; + } + + friendcon_id = create_friend_conn(fr_c); + + if (friendcon_id == -1) + return -1; + + int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key); + + if (onion_friendnum == -1) + return -1; + + Friend_Conn *friend_con = &fr_c->conns[friendcon_id]; + + friend_con->crypt_connection_id = -1; + friend_con->status = FRIENDCONN_STATUS_CONNECTING; + memcpy(friend_con->real_public_key, real_public_key, crypto_box_PUBLICKEYBYTES); + friend_con->onion_friendnum = onion_friendnum; + + recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id); + onion_dht_pk_callback(fr_c->onion_c, onion_friendnum, &dht_pk_callback, fr_c, friendcon_id); + + return friendcon_id; +} + +/* Kill a friend connection. + * + * return -1 on failure. + * return 0 on success. + */ +int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id) +{ + Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); + + if (!friend_con) + return -1; + + if (friend_con->lock_count) { + --friend_con->lock_count; + return 0; + } + + onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum); + crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); + + if (friend_con->dht_lock) { + DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock); + } + + return wipe_friend_conn(fr_c, friendcon_id); +} + + +/* Create new friend_connections instance. */ +Friend_Connections *new_friend_connections(Onion_Client *onion_c) +{ + if (!onion_c) + return NULL; + + Friend_Connections *temp = calloc(1, sizeof(Friend_Connections)); + + if (temp == NULL) + return NULL; + + temp->dht = onion_c->dht; + temp->net_crypto = onion_c->c; + temp->onion_c = onion_c; + + new_connection_handler(temp->net_crypto, &handle_new_connections, temp); + + return temp; +} + +/* main friend_connections loop. */ +void do_friend_connections(Friend_Connections *fr_c) +{ + uint32_t i; + uint64_t temp_time = unix_time(); + + for (i = 0; i < fr_c->num_cons; ++i) { + Friend_Conn *friend_con = get_conn(fr_c, i); + + if (friend_con) { + if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) { + if (friend_con->dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { + if (friend_con->dht_lock) { + DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock); + friend_con->dht_lock = 0; + } + } + + if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { + friend_con->dht_ip_port.ip.family = 0; + } + + if (friend_con->dht_lock) { + if (friend_new_connection(fr_c, i) == 0) { + set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_temp_pk); + set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); + } + } + + } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) { + if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { + send_ping(fr_c, i); + } + + if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { + /* If we stopped receiving ping packets, kill it. */ + crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); + friend_con->crypt_connection_id = -1; + handle_status(fr_c, i, 0); /* Going offline. */ + } + } + } + } +} + +/* Free everything related with friend_connections. */ +void kill_friend_connections(Friend_Connections *fr_c) +{ + if (!fr_c) + return; + + uint32_t i; + + for (i = 0; i < fr_c->num_cons; ++i) { + kill_friend_connection(fr_c, i); + } + + free(fr_c); +} diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h new file mode 100644 index 00000000..62b82dc2 --- /dev/null +++ b/toxcore/friend_connection.h @@ -0,0 +1,140 @@ +/* friend_connection.h + * + * Connection to friends. + * + * Copyright (C) 2014 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + + +#ifndef FRIEND_CONNECTION_H +#define FRIEND_CONNECTION_H + +#include "net_crypto.h" +#include "DHT.h" +#include "LAN_discovery.h" +#include "onion_client.h" + + +#define MAX_FRIEND_CONNECTION_CALLBACKS 2 +#define MESSENGER_CALLBACK_INDEX 0 +#define GROUPCHAT_CALLBACK_INDEX 1 + +#define PACKET_ID_ALIVE 16 + +/* Interval between the sending of ping packets. */ +#define FRIEND_PING_INTERVAL 6 + +/* If no packets are received from friend in this time interval, kill the connection. */ +#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3) + +/* Time before friend is removed from the DHT after last hearing about him. */ +#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT + + +enum { + FRIENDCONN_STATUS_NONE, + FRIENDCONN_STATUS_CONNECTING, + FRIENDCONN_STATUS_CONNECTED +}; + +typedef struct { + uint8_t status; + + uint8_t real_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; + uint16_t dht_lock; + IP_Port dht_ip_port; + uint64_t dht_ping_lastrecv, dht_ip_port_lastrecv; + + int onion_friendnum; + int crypt_connection_id; + + uint64_t ping_lastrecv, ping_lastsent; + + struct { + int (*status_callback)(void *object, int id, uint8_t status); + void *status_callback_object; + int status_callback_id; + + int (*data_callback)(void *object, int id, uint8_t *data, uint16_t length); + void *data_callback_object; + int data_callback_id; + + int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length); + void *lossy_data_callback_object; + int lossy_data_callback_id; + } callbacks[MAX_FRIEND_CONNECTION_CALLBACKS]; + + uint16_t lock_count; +} Friend_Conn; + + +typedef struct { + Net_Crypto *net_crypto; + DHT *dht; + Onion_Client *onion_c; + + Friend_Conn *conns; + uint32_t num_cons; + +} Friend_Connections; + +/* Set the callbacks for the friend connection. + * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array. + * + * return 0 on success. + * return -1 on failure + */ +int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, + int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data, + uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, + int number); + +/* return the crypt_connection_id for the connection. + * + * return crypt_connection_id on success. + * return -1 on failure. + */ +int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id); + +/* Create a new friend connection. + * If one to that real public key already exists, increase lock count and return it. + * + * return -1 on failure. + * return connection id on success. + */ +int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key); + +/* Kill a friend connection. + * + * return -1 on failure. + * return 0 on success. + */ +int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id); + +/* Create new friend_connections instance. */ +Friend_Connections *new_friend_connections(Onion_Client *onion_c); + +/* main friend_connections loop. */ +void do_friend_connections(Friend_Connections *fr_c); + +/* Free everything related with friend_connections. */ +void kill_friend_connections(Friend_Connections *fr_c); + +#endif -- cgit v1.2.3 From 230a65c91fa6e58f32d67cc21547fe507eedaeee Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 27 Sep 2014 20:01:41 -0400 Subject: Removed send_group_message_packet and its callback function from Messenger. --- toxcore/Messenger.c | 32 ++----------------------------- toxcore/Messenger.h | 13 ------------- toxcore/group.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++---- toxcore/group.h | 3 +-- 4 files changed, 54 insertions(+), 49 deletions(-) (limited to 'toxcore/Messenger.h') diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 04830260..c3f85beb 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -999,14 +999,6 @@ void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_ m->group_invite = function; } -/* Set the callback for group messages. - * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) - */ -void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)) -{ - m->group_message = function; -} /* Send a group invite packet. * @@ -1018,17 +1010,6 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, data, length, 0); } -/* Send a group message packet. - * - * return 1 on success - * return 0 on failure - */ -int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) -{ - return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE_GROUPCHAT, data, length, 0); -} - - /****************FILE SENDING*****************/ @@ -1230,7 +1211,8 @@ int file_data(const Messenger *m, int32_t friendnumber, uint8_t filenumber, cons return -1; /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */ - if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) + if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) return -1; uint8_t packet[MAX_CRYPTO_DATA_SIZE]; @@ -2125,16 +2107,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; } - case PACKET_ID_MESSAGE_GROUPCHAT: { - if (data_length == 0) - break; - - if (m->group_message) - (*m->group_message)(m, i, data, data_length); - - break; - } - case PACKET_ID_FILE_SENDREQUEST: { if (data_length < 1 + sizeof(uint64_t) + 1) break; diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 454c31cb..38543b36 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -729,12 +729,6 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t */ void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)); -/* Set the callback for group messages. - * - * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length) - */ -void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t)); - /* Send a group invite packet. * * return 1 on success @@ -742,13 +736,6 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32 */ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); -/* Send a group message packet. - * - * return 1 on success - * return 0 on failure - */ -int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); - /****************FILE SENDING*****************/ diff --git a/toxcore/group.c b/toxcore/group.c index 8ea626bb..d5244f65 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -223,6 +223,8 @@ static int addpeer(Group_c *chat, const uint8_t *client_id, uint16_t peer_number return (chat->numpeers - 1); } +static int handle_packet(void *object, int number, uint8_t *data, uint16_t length); + /* Add friend to group chat. * * return 0 on success @@ -246,7 +248,7 @@ static int add_friend_to_groupchat(Group_Chats *g_c, int32_t friendnumber, int g continue; } - if (g->close[i].type == GROUPCHAT_CLOSE_FRIEND && g->close[i].number == (uint32_t)friendnumber) { + if (g->close[i].type == GROUPCHAT_CLOSE_CONNECTION && g->close[i].number == (uint32_t)friendnumber) { g->close[i].group_number = other_groupnum; /* update groupnum. */ return 0; /* Already in list. */ } @@ -257,9 +259,13 @@ static int add_friend_to_groupchat(Group_Chats *g_c, int32_t friendnumber, int g if (ind == MAX_GROUP_CONNECTIONS) return -1; - g->close[ind].type = GROUPCHAT_CLOSE_FRIEND; + g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; g->close[ind].number = friendnumber; g->close[ind].group_number = other_groupnum; + int friendcon_id = g_c->m->friendlist[friendnumber].friendcon_id; + //TODO + friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, 0, &handle_packet, 0, g_c->m, + friendnumber); return 0; } @@ -300,6 +306,23 @@ int del_groupchat(Group_Chats *g_c, int groupnumber) return wipe_group_chat(g_c, groupnumber); } +/* Send a group message packet. + * + * return 1 on success + * return 0 on failure + */ +int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) +{ + if (length >= MAX_CRYPTO_DATA_SIZE) + return 0; + + uint8_t packet[1 + length]; + packet[0] = PACKET_ID_MESSAGE_GROUPCHAT; + memcpy(packet + 1, data, length); + return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, + m->friendlist[friendnumber].friendcon_id), packet, sizeof(packet), 0) != -1; +} + #define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) #define INVITE_ID 0 @@ -464,7 +487,7 @@ static int friend_in_close(Group_c *g, int32_t friendnumber) int i; for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { - if (g->close[i].type != GROUPCHAT_CLOSE_FRIEND) + if (g->close[i].type != GROUPCHAT_CLOSE_CONNECTION) continue; if (g->close[i].number != (uint32_t)friendnumber) @@ -649,6 +672,31 @@ static void handle_friend_message_packet(Messenger *m, int32_t friendnumber, con handle_message_packet_group(g_c, groupnumber, data, length, index); } +static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) +{ + if (length <= 1) + return -1; + + switch (data[0]) { + case PACKET_ID_INVITE_GROUPCHAT: { + handle_friend_invite_packet(object, number, data + 1, length - 1); + break; + } + + case PACKET_ID_MESSAGE_GROUPCHAT: { + handle_friend_message_packet(object, number, data + 1, length - 1); + break; + } + + default: { + return 0; + } + } + + return 0; +} + + /* Create new groupchat instance. */ Group_Chats *new_groupchats(Messenger *m) { @@ -663,7 +711,6 @@ Group_Chats *new_groupchats(Messenger *m) temp->m = m; m->group_chat_object = temp; m_callback_group_invite(m, &handle_friend_invite_packet); - m_callback_group_message(m, &handle_friend_message_packet); return temp; } diff --git a/toxcore/group.h b/toxcore/group.h index ab36ca34..a5b5723c 100644 --- a/toxcore/group.h +++ b/toxcore/group.h @@ -56,8 +56,7 @@ typedef struct { enum { GROUPCHAT_CLOSE_NONE, - GROUPCHAT_CLOSE_FRIEND, - GROUPCHAT_CLOSE_GROUPCON + GROUPCHAT_CLOSE_CONNECTION }; typedef struct { -- cgit v1.2.3