1 /* SPDX-License-Identifier: GPL-3.0-or-later 2 * Copyright © 2016-2018 The TokTok team. 3 * Copyright © 2014 Tox project. 4 */ 5 6 /* 7 * Slightly better groupchats implementation. 8 */ 9 #ifndef C_TOXCORE_TOXCORE_GROUP_H 10 #define C_TOXCORE_TOXCORE_GROUP_H 11 12 #include "Messenger.h" 13 14 typedef enum Groupchat_Status { 15 GROUPCHAT_STATUS_NONE, 16 GROUPCHAT_STATUS_VALID, 17 GROUPCHAT_STATUS_CONNECTED, 18 } Groupchat_Status; 19 20 typedef enum Groupchat_Type { 21 GROUPCHAT_TYPE_TEXT, 22 GROUPCHAT_TYPE_AV, 23 } Groupchat_Type; 24 25 #define MAX_LOSSY_COUNT 256 26 27 typedef struct Message_Info { 28 uint32_t message_number; 29 uint8_t message_id; 30 } Message_Info; 31 32 #define MAX_LAST_MESSAGE_INFOS 8 33 34 typedef struct Group_Peer { 35 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; 36 uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; 37 bool temp_pk_updated; 38 bool is_friend; 39 40 uint64_t last_active; 41 42 Message_Info 43 last_message_infos[MAX_LAST_MESSAGE_INFOS]; /* received messages, strictly decreasing in message_number */ 44 uint8_t num_last_message_infos; 45 46 uint8_t nick[MAX_NAME_LENGTH]; 47 uint8_t nick_len; 48 bool nick_updated; 49 50 uint16_t peer_number; 51 52 uint8_t recv_lossy[MAX_LOSSY_COUNT]; 53 uint16_t bottom_lossy_number; 54 uint16_t top_lossy_number; 55 56 void *object; 57 } Group_Peer; 58 59 #define DESIRED_CLOSEST 4 60 #define MAX_GROUP_CONNECTIONS 16 61 #define GROUP_ID_LENGTH CRYPTO_SYMMETRIC_KEY_SIZE 62 63 typedef enum Groupchat_Connection_Type { 64 GROUPCHAT_CONNECTION_NONE, 65 GROUPCHAT_CONNECTION_CONNECTING, 66 GROUPCHAT_CONNECTION_ONLINE, 67 } Groupchat_Connection_Type; 68 69 /* Connection is to one of the closest DESIRED_CLOSEST peers */ 70 #define GROUPCHAT_CONNECTION_REASON_CLOSEST (1 << 0) 71 72 /* Connection is to a peer we are introducing to the conference */ 73 #define GROUPCHAT_CONNECTION_REASON_INTRODUCING (1 << 1) 74 75 /* Connection is to a peer who is introducing us to the conference */ 76 #define GROUPCHAT_CONNECTION_REASON_INTRODUCER (1 << 2) 77 78 typedef struct Groupchat_Connection { 79 uint8_t type; /* `GROUPCHAT_CONNECTION_*` */ 80 uint8_t reasons; /* bit field with flags `GROUPCHAT_CONNECTION_REASON_*` */ 81 uint32_t number; 82 uint16_t group_number; 83 } Groupchat_Connection; 84 85 typedef struct Groupchat_Closest { 86 uint8_t entry; 87 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; 88 uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; 89 } Groupchat_Closest; 90 91 typedef void peer_on_join_cb(void *object, uint32_t conference_number, uint32_t peer_number); 92 typedef void peer_on_leave_cb(void *object, uint32_t conference_number, void *peer_object); 93 typedef void group_on_delete_cb(void *object, uint32_t conference_number); 94 95 // maximum number of frozen peers to store; group_set_max_frozen() overrides. 96 #define MAX_FROZEN_DEFAULT 128 97 98 typedef struct Group_c { 99 uint8_t status; 100 101 bool need_send_name; 102 bool title_fresh; 103 104 Group_Peer *group; 105 uint32_t numpeers; 106 107 Group_Peer *frozen; 108 uint32_t numfrozen; 109 110 uint32_t maxfrozen; 111 112 Groupchat_Connection connections[MAX_GROUP_CONNECTIONS]; 113 114 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; 115 Groupchat_Closest closest_peers[DESIRED_CLOSEST]; 116 uint8_t changed; 117 118 uint8_t type; 119 uint8_t id[GROUP_ID_LENGTH]; 120 121 uint8_t title[MAX_NAME_LENGTH]; 122 uint8_t title_len; 123 124 uint32_t message_number; 125 uint16_t lossy_message_number; 126 uint16_t peer_number; 127 128 uint64_t last_sent_ping; 129 130 uint32_t num_introducer_connections; 131 132 void *object; 133 134 peer_on_join_cb *peer_on_join; 135 peer_on_leave_cb *peer_on_leave; 136 group_on_delete_cb *group_on_delete; 137 } Group_c; 138 139 /* Callback for group invites. 140 * 141 * data of length is what needs to be passed to join_groupchat(). 142 */ 143 typedef void g_conference_invite_cb(Messenger *m, uint32_t friend_number, int type, const uint8_t *cookie, 144 size_t length, void *user_data); 145 146 /* Callback for group connection. */ 147 typedef void g_conference_connected_cb(Messenger *m, uint32_t conference_number, void *user_data); 148 149 /* Callback for group messages. */ 150 typedef void g_conference_message_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, int type, 151 const uint8_t *message, size_t length, void *user_data); 152 153 /* Callback for peer nickname changes. */ 154 typedef void peer_name_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, const uint8_t *name, 155 size_t length, void *user_data); 156 157 /* Set callback function for peer list changes. */ 158 typedef void peer_list_changed_cb(Messenger *m, uint32_t conference_number, void *user_data); 159 160 /* Callback for title changes. 161 * 162 * If peer_number == -1, then author is unknown (e.g. initial joining the group). 163 */ 164 typedef void title_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, const uint8_t *title, 165 size_t length, void *user_data); 166 167 /* Callback for lossy packets. 168 * 169 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed. 170 */ 171 typedef int lossy_packet_cb(void *object, uint32_t conference_number, uint32_t peer_number, void *peer_object, 172 const uint8_t *packet, uint16_t length); 173 174 typedef struct Group_Lossy_Handler { 175 lossy_packet_cb *function; 176 } Group_Lossy_Handler; 177 178 typedef struct Group_Chats { 179 const Mono_Time *mono_time; 180 181 Messenger *m; 182 Friend_Connections *fr_c; 183 184 Group_c *chats; 185 uint16_t num_chats; 186 187 g_conference_invite_cb *invite_callback; 188 g_conference_connected_cb *connected_callback; 189 g_conference_message_cb *message_callback; 190 peer_name_cb *peer_name_callback; 191 peer_list_changed_cb *peer_list_changed_callback; 192 title_cb *title_callback; 193 194 Group_Lossy_Handler lossy_packethandlers[256]; 195 } Group_Chats; 196 197 /* Set the callback for group invites. */ 198 void g_callback_group_invite(Group_Chats *g_c, g_conference_invite_cb *function); 199 200 /* Set the callback for group connection. */ 201 void g_callback_group_connected(Group_Chats *g_c, g_conference_connected_cb *function); 202 203 /* Set the callback for group messages. */ 204 void g_callback_group_message(Group_Chats *g_c, g_conference_message_cb *function); 205 206 207 /* Set callback function for title changes. */ 208 void g_callback_group_title(Group_Chats *g_c, title_cb *function); 209 210 /* Set callback function for peer nickname changes. 211 * 212 * It gets called every time a peer changes their nickname. 213 */ 214 void g_callback_peer_name(Group_Chats *g_c, peer_name_cb *function); 215 216 /* Set callback function for peer list changes. 217 * 218 * It gets called every time the name list changes(new peer, deleted peer) 219 */ 220 void g_callback_peer_list_changed(Group_Chats *g_c, peer_list_changed_cb *function); 221 222 /* Creates a new groupchat and puts it in the chats array. 223 * 224 * type is one of `GROUPCHAT_TYPE_*` 225 * 226 * return group number on success. 227 * return -1 on failure. 228 */ 229 int add_groupchat(Group_Chats *g_c, uint8_t type); 230 231 /* Delete a groupchat from the chats array, informing the group first as 232 * appropriate. 233 * 234 * return 0 on success. 235 * return -1 if groupnumber is invalid. 236 */ 237 int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently); 238 239 /* Copy the public key of (frozen, if frozen is true) peernumber who is in 240 * groupnumber to pk. 241 * pk must be CRYPTO_PUBLIC_KEY_SIZE long. 242 * 243 * return 0 on success 244 * return -1 if groupnumber is invalid. 245 * return -2 if peernumber is invalid. 246 */ 247 int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, uint8_t *pk, bool frozen); 248 249 /* 250 * Return the size of (frozen, if frozen is true) peernumber's name. 251 * 252 * return -1 if groupnumber is invalid. 253 * return -2 if peernumber is invalid. 254 */ 255 int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, bool frozen); 256 257 /* Copy the name of (frozen, if frozen is true) peernumber who is in 258 * groupnumber to name. 259 * name must be at least MAX_NAME_LENGTH long. 260 * 261 * return length of name if success 262 * return -1 if groupnumber is invalid. 263 * return -2 if peernumber is invalid. 264 */ 265 int group_peername(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, uint8_t *name, bool frozen); 266 267 /* Copy last active timestamp of frozen peernumber who is in groupnumber to 268 * last_active. 269 * 270 * return 0 on success. 271 * return -1 if groupnumber is invalid. 272 * return -2 if peernumber is invalid. 273 */ 274 int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, 275 uint64_t *last_active); 276 277 /* Set maximum number of frozen peers. 278 * 279 * return 0 on success. 280 * return -1 if groupnumber is invalid. 281 */ 282 int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t maxfrozen); 283 284 /* invite friendnumber to groupnumber 285 * 286 * return 0 on success. 287 * return -1 if groupnumber is invalid. 288 * return -2 if invite packet failed to send. 289 */ 290 int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber); 291 292 /* Join a group (you need to have been invited first.) 293 * 294 * expected_type is the groupchat type we expect the chat we are joining to 295 * have. 296 * 297 * return group number on success. 298 * return -1 if data length is invalid. 299 * return -2 if group is not the expected type. 300 * return -3 if friendnumber is invalid. 301 * return -4 if client is already in this group. 302 * return -5 if group instance failed to initialize. 303 * return -6 if join packet fails to send. 304 */ 305 int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_type, const uint8_t *data, 306 uint16_t length); 307 308 /* send a group message 309 * return 0 on success 310 * see: send_message_group() for error codes. 311 */ 312 int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *message, uint16_t length); 313 314 /* send a group action 315 * return 0 on success 316 * see: send_message_group() for error codes. 317 */ 318 int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *action, uint16_t length); 319 320 /* set the group's title, limited to MAX_NAME_LENGTH 321 * return 0 on success 322 * return -1 if groupnumber is invalid. 323 * return -2 if title is too long or empty. 324 * return -3 if packet fails to send. 325 */ 326 int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *title, uint8_t title_len); 327 328 329 /* return the group's title size. 330 * return -1 of groupnumber is invalid. 331 * return -2 if title is too long or empty. 332 */ 333 int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber); 334 335 /* Get group title from groupnumber and put it in title. 336 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. 337 * 338 * return length of copied title if success. 339 * return -1 if groupnumber is invalid. 340 * return -2 if title is too long or empty. 341 */ 342 int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title); 343 344 /* Return the number of (frozen, if frozen is true) peers in the group chat on 345 * success. 346 * return -1 if groupnumber is invalid. 347 */ 348 int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber, bool frozen); 349 350 /* return 1 if the peernumber corresponds to ours. 351 * return 0 if the peernumber is not ours. 352 * return -1 if groupnumber is invalid. 353 * return -2 if peernumber is invalid. 354 * return -3 if we are not connected to the group chat. 355 */ 356 int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber); 357 358 /* Set handlers for custom lossy packets. */ 359 void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, lossy_packet_cb *function); 360 361 /* High level function to send custom lossy packets. 362 * 363 * return -1 on failure. 364 * return 0 on success. 365 */ 366 int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length); 367 368 /* Return the number of chats in the instance m. 369 * You should use this to determine how much memory to allocate 370 * for copy_chatlist. 371 */ 372 uint32_t count_chatlist(const Group_Chats *g_c); 373 374 /* Copy a list of valid chat IDs into the array out_list. 375 * If out_list is NULL, returns 0. 376 * Otherwise, returns the number of elements copied. 377 * If the array was too small, the contents 378 * of out_list will be truncated to list_size. */ 379 uint32_t copy_chatlist(const Group_Chats *g_c, uint32_t *out_list, uint32_t list_size); 380 381 /* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is. 382 * 383 * return -1 on failure. 384 * return type on success. 385 */ 386 int group_get_type(const Group_Chats *g_c, uint32_t groupnumber); 387 388 /* Copies the unique id of `group_chat[groupnumber]` into id. 389 * 390 * return false on failure. 391 * return true on success. 392 */ 393 bool conference_get_id(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *id); 394 395 int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id); 396 397 /* Send current name (set in messenger) to all online groups. 398 */ 399 void send_name_all_groups(Group_Chats *g_c); 400 401 /* Set the object that is tied to the group chat. 402 * 403 * return 0 on success. 404 * return -1 on failure 405 */ 406 int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object); 407 408 /* Set the object that is tied to the group peer. 409 * 410 * return 0 on success. 411 * return -1 on failure 412 */ 413 int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, void *object); 414 415 /* Return the object tied to the group chat previously set by group_set_object. 416 * 417 * return NULL on failure. 418 * return object on success. 419 */ 420 void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber); 421 422 /* Return the object tied to the group chat peer previously set by group_peer_set_object. 423 * 424 * return NULL on failure. 425 * return object on success. 426 */ 427 void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber); 428 429 /* Set a function to be called when a new peer joins a group chat. 430 * 431 * return 0 on success. 432 * return -1 on failure. 433 */ 434 int callback_groupchat_peer_new(const Group_Chats *g_c, uint32_t groupnumber, peer_on_join_cb *function); 435 436 /* Set a function to be called when a peer leaves a group chat. 437 * 438 * return 0 on success. 439 * return -1 on failure. 440 */ 441 int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_on_leave_cb *function); 442 443 /* Set a function to be called when the group chat is deleted. 444 * 445 * return 0 on success. 446 * return -1 on failure. 447 */ 448 int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); 449 450 /* Return size of the conferences data (for saving). */ 451 uint32_t conferences_size(const Group_Chats *g_c); 452 453 /* Save the conferences in data (must be allocated memory of size at least conferences_size()) */ 454 uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data); 455 456 /** 457 * Load a state section. 458 * 459 * @param data Data to load 460 * @param length Length of data 461 * @param type Type of section (`STATE_TYPE_*`) 462 * @param status Result of loading section is stored here if the section is handled. 463 * @return true iff section handled. 464 */ 465 bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type, 466 State_Load_Status *status); 467 468 /* Create new groupchat instance. */ 469 Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m); 470 471 /* main groupchats loop. */ 472 void do_groupchats(Group_Chats *g_c, void *userdata); 473 474 /* Free everything related with group chats. */ 475 void kill_groupchats(Group_Chats *g_c); 476 477 #endif 478