/work/toxcore/group_connection.h
Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2020 The TokTok team. |
3 | | * Copyright © 2015 Tox project. |
4 | | */ |
5 | | |
6 | | /** |
7 | | * An implementation of massive text only group chats. |
8 | | */ |
9 | | |
10 | | #ifndef C_TOXCORE_TOXCORE_GROUP_CONNECTION_H |
11 | | #define C_TOXCORE_TOXCORE_GROUP_CONNECTION_H |
12 | | |
13 | | #include "DHT.h" |
14 | | #include "TCP_connection.h" |
15 | | #include "attributes.h" |
16 | | #include "crypto_core.h" |
17 | | #include "group_common.h" |
18 | | #include "logger.h" |
19 | | #include "mem.h" |
20 | | #include "mono_time.h" |
21 | | #include "network.h" |
22 | | |
23 | | /* Max number of TCP relays we share with a peer on handshake */ |
24 | 172 | #define GCC_MAX_TCP_SHARED_RELAYS 3 |
25 | | |
26 | | /** Marks a peer for deletion. If gconn is null or already marked for deletion this function has no effect. */ |
27 | | void gcc_mark_for_deletion(GC_Connection *_Nonnull gconn, TCP_Connections *_Nonnull tcp_conn, Group_Exit_Type type, |
28 | | const uint8_t *_Nullable part_message, uint16_t length); |
29 | | /** @brief Decides if message need to be put in recv_array or immediately handled. |
30 | | * |
31 | | * Return 3 if message is in correct sequence and is a fragment packet. |
32 | | * Return 2 if message is in correct sequence and may be handled immediately. |
33 | | * Return 1 if packet is out of sequence and added to recv_array. |
34 | | * Return 0 if message is a duplicate. |
35 | | * Return -1 on failure |
36 | | */ |
37 | | int gcc_handle_received_message(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, GC_Connection *_Nonnull gconn, |
38 | | const uint8_t *_Nullable data, uint16_t length, uint8_t packet_type, uint64_t message_id, |
39 | | bool direct_conn); |
40 | | /** @brief Handles a packet fragment. |
41 | | * |
42 | | * If the fragment is incomplete, it gets stored in the recv |
43 | | * array. Otherwise the segment is re-assembled into a complete |
44 | | * payload and processed. |
45 | | * |
46 | | * Return 1 if fragment is successfully handled and is not the end of the sequence. |
47 | | * Return 0 if fragment is the end of a sequence and successfully handled. |
48 | | * Return -1 on failure. |
49 | | */ |
50 | | int gcc_handle_packet_fragment(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat, uint32_t peer_number, GC_Connection *_Nonnull gconn, |
51 | | const uint8_t *_Nullable chunk, uint16_t length, uint8_t packet_type, uint64_t message_id, |
52 | | void *_Nullable userdata); |
53 | | /** @brief Return array index for message_id */ |
54 | | uint16_t gcc_get_array_index(uint64_t message_id); |
55 | | |
56 | | /** @brief Removes send_array item with message_id. |
57 | | * |
58 | | * Return true on success. |
59 | | */ |
60 | | bool gcc_handle_ack(const Logger *_Nonnull log, const Memory *_Nonnull mem, GC_Connection *_Nonnull gconn, uint64_t message_id); |
61 | | |
62 | | /** @brief Sets the send_message_id and send_array_start for `gconn` to `id`. |
63 | | * |
64 | | * This should only be used to initialize a new lossless connection. |
65 | | */ |
66 | | void gcc_set_send_message_id(GC_Connection *_Nonnull gconn, uint64_t id); |
67 | | |
68 | | /** @brief Sets the received_message_id for `gconn` to `id`. */ |
69 | | void gcc_set_recv_message_id(GC_Connection *_Nonnull gconn, uint64_t id); |
70 | | |
71 | | /** |
72 | | * @brief Returns true if the ip_port is set for gconn. |
73 | | */ |
74 | | bool gcc_ip_port_is_set(const GC_Connection *_Nonnull gconn); |
75 | | |
76 | | /** |
77 | | * @brief Sets the ip_port for gconn to ipp. |
78 | | * |
79 | | * If ipp is not set this function has no effect. |
80 | | */ |
81 | | void gcc_set_ip_port(GC_Connection *_Nonnull gconn, const IP_Port *_Nullable ipp); |
82 | | /** @brief Copies a random TCP relay node from gconn to tcp_node. |
83 | | * |
84 | | * Return true on success. |
85 | | */ |
86 | | bool gcc_copy_tcp_relay(const Random *_Nonnull rng, Node_format *_Nonnull tcp_node, const GC_Connection *_Nonnull gconn); |
87 | | |
88 | | /** @brief Saves tcp_node to gconn's list of connected tcp relays. |
89 | | * |
90 | | * If relays list is full a random node is overwritten with the new node. |
91 | | * |
92 | | * Return 0 on success. |
93 | | * Return -1 on failure. |
94 | | * Return -2 if node is already in list. |
95 | | */ |
96 | | int gcc_save_tcp_relay(const Random *_Nonnull rng, GC_Connection *_Nonnull gconn, const Node_format *_Nonnull tcp_node); |
97 | | |
98 | | /** @brief Checks for and handles messages that are in proper sequence in gconn's recv_array. |
99 | | * This should always be called after a new packet is successfully handled. |
100 | | */ |
101 | | void gcc_check_recv_array(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn, uint32_t peer_number, |
102 | | void *_Nullable userdata); |
103 | | /** @brief Attempts to re-send lossless packets that have not yet received an ack. */ |
104 | | void gcc_resend_packets(const GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn); |
105 | | |
106 | | /** |
107 | | * Uses public encryption key `sender_pk` and the shared secret key associated with `gconn` |
108 | | * to generate a shared 32-byte encryption key that can be used by the owners of both keys for symmetric |
109 | | * encryption and decryption. |
110 | | * |
111 | | * Puts the result in the shared session key buffer for `gconn`, which must have room for |
112 | | * CRYPTO_SHARED_KEY_SIZE bytes. This resulting shared key should be treated as a secret key. |
113 | | */ |
114 | | void gcc_make_session_shared_key(GC_Connection *_Nonnull gconn, const uint8_t *_Nonnull sender_pk); |
115 | | |
116 | | /** @brief Return true if we have a direct connection with `gconn`. */ |
117 | | bool gcc_conn_is_direct(const Mono_Time *_Nonnull mono_time, const GC_Connection *_Nonnull gconn); |
118 | | |
119 | | /** @brief Return true if we can try a direct connection with `gconn` again. */ |
120 | | bool gcc_conn_should_try_direct(const Mono_Time *_Nonnull mono_time, const GC_Connection *_Nonnull gconn); |
121 | | |
122 | | /** @brief Return true if a direct UDP connection is possible with `gconn`. */ |
123 | | bool gcc_direct_conn_is_possible(const GC_Chat *_Nonnull chat, const GC_Connection *_Nonnull gconn); |
124 | | |
125 | | /** @brief Sends a packet to the peer associated with gconn. |
126 | | * |
127 | | * This is a lower level function that does not encrypt or wrap the packet. |
128 | | * |
129 | | * Return true on success. |
130 | | */ |
131 | | bool gcc_send_packet(const GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn, const uint8_t *_Nonnull packet, uint16_t length); |
132 | | |
133 | | /** @brief Sends a lossless packet to `gconn` comprised of `data` of size `length`. |
134 | | * |
135 | | * This function will add the packet to the lossless send array, encrypt/wrap it using the |
136 | | * shared key associated with `gconn`, and try to send it over the wire. |
137 | | * |
138 | | * Return 0 if the packet was successfully encrypted and added to the send array. |
139 | | * Return -1 if the packet couldn't be added to the send array. |
140 | | * Return -2 if the packet failed to be wrapped or encrypted. |
141 | | */ |
142 | | int gcc_send_lossless_packet(const GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn, const uint8_t *_Nullable data, uint16_t length, |
143 | | uint8_t packet_type); |
144 | | /** @brief Splits a lossless packet up into fragments, wraps each fragment in a GP_FRAGMENT |
145 | | * header, encrypts them, and send them in succession. |
146 | | * |
147 | | * This function will first try to add each packet fragment to the send array as an atomic |
148 | | * unit. If any chunk fails to be added the process will be reversed and an error will be |
149 | | * returned. Otherwise it will then try to send all the fragments in succession. |
150 | | * |
151 | | * Return true if all fragments are successfully added to the send array. |
152 | | */ |
153 | | bool gcc_send_lossless_packet_fragments(const GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn, const uint8_t *_Nonnull data, uint16_t length, uint8_t packet_type); |
154 | | |
155 | | /** @brief Encrypts `data` of `length` bytes, designated by `message_id`, using the shared key |
156 | | * associated with `gconn` and sends lossless packet over the wire. |
157 | | * |
158 | | * This function does not add the packet to the send array. |
159 | | * |
160 | | * Return 0 on success. |
161 | | * Return -1 if packet wrapping and encryption fails. |
162 | | * Return -2 if the packet fails to send. |
163 | | */ |
164 | | int gcc_encrypt_and_send_lossless_packet(const GC_Chat *_Nonnull chat, GC_Connection *_Nonnull gconn, const uint8_t *_Nullable data, |
165 | | uint16_t length, uint64_t message_id, uint8_t packet_type); |
166 | | /** @brief Called when a peer leaves the group. */ |
167 | | void gcc_peer_cleanup(const Memory *_Nonnull mem, GC_Connection *_Nonnull gconn); |
168 | | |
169 | | /** @brief Called on group exit. */ |
170 | | void gcc_cleanup(const GC_Chat *_Nonnull chat); |
171 | | |
172 | | #endif /* C_TOXCORE_TOXCORE_GROUP_CONNECTION_H */ |