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