diff --git a/toxcore/group.c b/toxcore/group.c index e0938472..2df3729a 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -513,6 +513,29 @@ static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint return 0; } +static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len) +{ + if (title_len > MAX_NAME_LENGTH || title_len == 0) + return -1; + + Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) + return -1; + + /* same as already set? */ + if (g->title_len == title_len && !memcmp(g->title, title, title_len)) + return 0; + + memcpy(g->title, title, title_len); + g->title_len = title_len; + + if (g_c->title_callback) + g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, g_c->title_callback_userdata); + + return 0; +} + static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) { Group_c *g = get_group_c(g_c, groupnumber); @@ -988,6 +1011,18 @@ void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenge g_c->group_namelistchange_userdata = userdata; } +/* Set callback function for title changes. + * + * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata) + * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) + */ +void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, + void *), void *userdata) +{ + g_c->title_callback = function; + g_c->title_callback_userdata = userdata; +} + /* Set a function to be called when a new peer joins a group chat. * * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber) @@ -1117,6 +1152,35 @@ static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_ } } +#define GROUP_MESSAGE_TITLE_ID 49 + +/* set the group's title, limited to MAX_NAME_LENGTH + * return 0 on success + * return -1 on failure + */ +int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len) +{ + if (title_len > MAX_NAME_LENGTH || title_len == 0) + return -1; + + Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) + return -1; + + /* same as already set? */ + if (g->title_len == title_len && !memcmp(g->title, title, title_len)) + return 0; + + memcpy(g->title, title, title_len); + g->title_len = title_len; + + if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len)) + return 0; + else + return -1; +} + 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; @@ -1285,6 +1349,8 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *dat #define PEER_KILL_ID 1 #define PEER_QUERY_ID 8 #define PEER_RESPONSE_ID 9 +#define PEER_TITLE_ID 10 +// we could send title with invite, but then if it changes between sending and accepting inv, joinee won't see it /* return 1 on success. * return 0 on failure @@ -1354,6 +1420,13 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_ } } + uint8_t Packet[2 + MAX_NAME_LENGTH]; + Packet[0] = PEER_TITLE_ID; + Packet[1] = g->title_len; + memcpy(Packet + 2, g->title, g->title_len); + send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, Packet, sizeof(Packet)); + // doesn't really matter if it makes it or not + return sent; } @@ -1438,6 +1511,11 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_ break; + case PEER_TITLE_ID: { + settitle(g_c, groupnumber, -1, data + 2, data[1]); + } + + break; } } @@ -1679,6 +1757,12 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const } break; + case GROUP_MESSAGE_TITLE_ID: { + if (settitle(g_c, groupnumber, index, msg_data, msg_data_len) == -1) + return; + } + break; + case PACKET_ID_MESSAGE: { if (msg_data_len == 0) return; diff --git a/toxcore/group.h b/toxcore/group.h index 46af35e3..775f14eb 100644 --- a/toxcore/group.h +++ b/toxcore/group.h @@ -60,7 +60,7 @@ typedef struct { #define DESIRED_CLOSE_CONNECTIONS 4 #define MAX_GROUP_CONNECTIONS 16 -#define GROUP_IDENTIFIER_LENGTH (1 + crypto_box_KEYBYTES) /* crypto_box_KEYBYTES so we can use new_symmetric_key(...) to fill it */ +#define GROUP_IDENTIFIER_LENGTH (1 + crypto_box_KEYBYTES) /* type + crypto_box_KEYBYTES so we can use new_symmetric_key(...) to fill it */ enum { GROUPCHAT_CLOSE_NONE, @@ -91,6 +91,9 @@ typedef struct { uint8_t identifier[GROUP_IDENTIFIER_LENGTH]; + uint8_t title[MAX_NAME_LENGTH]; + uint8_t title_len; + uint32_t message_number; uint16_t lossy_message_number; uint16_t peer_number; @@ -121,6 +124,8 @@ typedef struct { void *action_callback_userdata; void (*peer_namelistchange)(Messenger *m, int, int, uint8_t, void *); void *group_namelistchange_userdata; + void (*title_callback)(Messenger *m, int, int, const uint8_t *, uint8_t, void *); + void *title_callback_userdata; struct { int (*function)(void *, int, int, void *, const uint8_t *, uint16_t); @@ -150,6 +155,14 @@ void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, i 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 title changes. + * + * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata) + * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) + */ +void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, + void *), void *userdata); + /* Set callback function for peer name list changes. * * It gets called every time the name list changes(new peer/name, deleted peer) @@ -214,6 +227,12 @@ int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *m */ int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length); +/* set the group's title, limited to MAX_NAME_LENGTH + * return 0 on success + * return -1 on failure + */ +int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len); + /* Return the number of peers in the group chat on success. * return -1 on failure */ diff --git a/toxcore/tox.c b/toxcore/tox.c index 32d7f7a0..8cef64cb 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -584,6 +584,18 @@ void tox_callback_group_action(Tox *tox, void (*function)(Messenger *tox, int, i g_callback_group_action(m->group_chat_object, function, userdata); } +/* Set callback function for title changes. + * + * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata) + * if peernumber == -1, then author is unknown (e.g. initial joining the group) + */ +void tox_callback_group_title(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint8_t, + void *), void *userdata) +{ + Messenger *m = tox; + g_callback_group_title(m->group_chat_object, function, userdata); +} + /* Set callback function for peer name list changes. * * It gets called every time the name list changes(new peer/name, deleted peer) @@ -671,6 +683,16 @@ int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint return group_action_send(m->group_chat_object, groupnumber, action, length); } +/* set the group's title, limited to MAX_NAME_LENGTH + * return 0 on success + * return -1 on failure + */ +int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length) +{ + Messenger *m = tox; + return group_title_send(m->group_chat_object, groupnumber, title, length); +} + /* Check if the current peernumber corresponds to ours. * * return 1 if the peernumber corresponds to ours. diff --git a/toxcore/tox.h b/toxcore/tox.h index e2f3bc3d..9d239ef1 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -452,6 +452,14 @@ void tox_callback_group_message(Tox *tox, void (*function)(Tox *tox, int, int, c void tox_callback_group_action(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *), void *userdata); +/* Set callback function for title changes. + * + * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata) + * if peernumber == -1, then author is unknown (e.g. initial joining the group) + */ +void tox_callback_group_title(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint8_t, + void *), void *userdata); + /* Set callback function for peer name list changes. * * It gets called every time the name list changes(new peer/name, deleted peer) @@ -514,6 +522,12 @@ int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, ui */ int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length); +/* set the group's title, limited to MAX_NAME_LENGTH + * return 0 on success + * return -1 on failure + */ +int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length); + /* Check if the current peernumber corresponds to ours. * * return 1 if the peernumber corresponds to ours.