From d5d84818fecc62425281aaf0cbe71d0f264fdc18 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 25 Sep 2014 21:05:17 -0400 Subject: [PATCH] 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(-) 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; }