/work/auto_tests/scenarios/scenario_group_tcp_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "framework/framework.h" |
2 | | #include <stdio.h> |
3 | | #include <string.h> |
4 | | #include <stdlib.h> |
5 | | |
6 | 10 | #define CODEWORD "RONALD MCDONALD" |
7 | 8 | #define CODEWORD_LEN (sizeof(CODEWORD) - 1) |
8 | 1 | #define RELAY_TCP_PORT 33811 |
9 | | |
10 | | typedef struct { |
11 | | uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; |
12 | | uint32_t group_number; |
13 | | uint32_t peer_id; |
14 | | bool joined; |
15 | | bool got_private_message; |
16 | | bool got_group_message; |
17 | | bool got_invite; |
18 | | } State; |
19 | | |
20 | | static void on_group_invite(const Tox_Event_Group_Invite *event, void *user_data) |
21 | 1 | { |
22 | 1 | ToxNode *self = (ToxNode *)user_data; |
23 | 1 | State *state = (State *)tox_node_get_script_ctx(self); |
24 | | |
25 | 1 | const uint32_t friend_number = tox_event_group_invite_get_friend_number(event); |
26 | 1 | const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event); |
27 | 1 | const size_t length = tox_event_group_invite_get_invite_data_length(event); |
28 | | |
29 | 1 | Tox_Err_Group_Invite_Accept err_accept; |
30 | 1 | state->group_number = tox_group_invite_accept(tox_node_get_tox(self), friend_number, invite_data, length, (const uint8_t *)"test", 4, |
31 | 1 | nullptr, 0, &err_accept); |
32 | 1 | if (err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK) { |
33 | 1 | state->got_invite = true; |
34 | 1 | } |
35 | 1 | } |
36 | | |
37 | | static void on_group_peer_join(const Tox_Event_Group_Peer_Join *event, void *user_data) |
38 | 25 | { |
39 | 25 | ToxNode *self = (ToxNode *)user_data; |
40 | 25 | State *state = (State *)tox_node_get_script_ctx(self); |
41 | 25 | state->peer_id = tox_event_group_peer_join_get_peer_id(event); |
42 | 25 | state->joined = true; |
43 | 25 | tox_node_log(self, "Peer %u joined group", state->peer_id); |
44 | 25 | } |
45 | | |
46 | | static void on_group_private_message(const Tox_Event_Group_Private_Message *event, void *user_data) |
47 | 2 | { |
48 | 2 | ToxNode *self = (ToxNode *)user_data; |
49 | 2 | State *state = (State *)tox_node_get_script_ctx(self); |
50 | 2 | const uint8_t *message = tox_event_group_private_message_get_message(event); |
51 | 2 | const size_t length = tox_event_group_private_message_get_message_length(event); |
52 | | |
53 | 2 | if (length == CODEWORD_LEN && memcmp(CODEWORD, message, length) == 0) { |
54 | 2 | state->got_private_message = true; |
55 | 2 | } |
56 | 2 | } |
57 | | |
58 | | static void on_group_message(const Tox_Event_Group_Message *event, void *user_data) |
59 | 1 | { |
60 | 1 | ToxNode *self = (ToxNode *)user_data; |
61 | 1 | State *state = (State *)tox_node_get_script_ctx(self); |
62 | 1 | const uint8_t *message = tox_event_group_message_get_message(event); |
63 | 1 | const size_t length = tox_event_group_message_get_message_length(event); |
64 | | |
65 | 1 | if (length == CODEWORD_LEN && memcmp(CODEWORD, message, length) == 0) { |
66 | 1 | state->got_group_message = true; |
67 | 1 | } |
68 | 1 | } |
69 | | |
70 | | static void alice_script(ToxNode *self, void *ctx) |
71 | 1 | { |
72 | 1 | State *state = (State *)ctx; |
73 | 1 | Tox *tox = tox_node_get_tox(self); |
74 | | |
75 | 1 | tox_events_callback_group_peer_join(tox_node_get_dispatch(self), on_group_peer_join); |
76 | | |
77 | 1 | Tox_Err_Group_New new_err; |
78 | 1 | state->group_number = tox_group_new(tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4, |
79 | 1 | (const uint8_t *)"test", 4, &new_err); |
80 | 1 | ck_assert(new_err == TOX_ERR_GROUP_NEW_OK); |
81 | | |
82 | 1 | Tox_Err_Group_State_Query id_err; |
83 | 1 | tox_group_get_chat_id(tox, state->group_number, state->chat_id, &id_err); |
84 | 1 | ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK); |
85 | | |
86 | 1 | char chat_id_str[TOX_GROUP_CHAT_ID_SIZE * 2 + 1]; |
87 | 33 | for (int i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) { |
88 | 32 | snprintf(chat_id_str + i * 2, sizeof(chat_id_str) - i * 2, "%02X", state->chat_id[i]); |
89 | 32 | } |
90 | 1 | tox_node_log(self, "Created group with chat_id: %s", chat_id_str); |
91 | | |
92 | 1 | tox_scenario_barrier_wait(self); // Barrier 1: chat_id is ready for Bob |
93 | | |
94 | 1 | tox_node_log(self, "Waiting for Bob to join group..."); |
95 | 1 | WAIT_UNTIL(state->joined); |
96 | 1 | if (!state->joined) { |
97 | 0 | return; |
98 | 0 | } |
99 | | |
100 | 1 | Tox_Err_Group_Send_Private_Message perr; |
101 | 1 | tox_group_send_private_message(tox, state->group_number, state->peer_id, |
102 | 1 | TOX_MESSAGE_TYPE_NORMAL, |
103 | 1 | (const uint8_t *)CODEWORD, CODEWORD_LEN, &perr); |
104 | 1 | ck_assert(perr == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK); |
105 | | |
106 | 1 | tox_scenario_barrier_wait(self); // Barrier 2: PM sent, Bob leaving |
107 | 1 | tox_scenario_barrier_wait(self); // Barrier 3: Bob left |
108 | 1 | state->joined = false; |
109 | | |
110 | 1 | tox_node_log(self, "Inviting Bob back via friend invite..."); |
111 | 1 | Tox_Err_Group_Invite_Friend err_invite; |
112 | 1 | tox_group_invite_friend(tox, state->group_number, 0, &err_invite); |
113 | 1 | ck_assert(err_invite == TOX_ERR_GROUP_INVITE_FRIEND_OK); |
114 | | |
115 | 1 | WAIT_UNTIL(state->joined); |
116 | 1 | if (!state->joined) { |
117 | 0 | return; |
118 | 0 | } |
119 | | |
120 | 1 | Tox_Err_Group_Send_Message merr; |
121 | 1 | tox_group_send_message(tox, state->group_number, TOX_MESSAGE_TYPE_NORMAL, |
122 | 1 | (const uint8_t *)CODEWORD, CODEWORD_LEN, &merr); |
123 | 1 | ck_assert(merr == TOX_ERR_GROUP_SEND_MESSAGE_OK); |
124 | 1 | } |
125 | | |
126 | | static void bob_script(ToxNode *self, void *ctx) |
127 | 1 | { |
128 | 1 | State *state = (State *)ctx; |
129 | 1 | Tox *tox = tox_node_get_tox(self); |
130 | | |
131 | 1 | tox_events_callback_group_private_message(tox_node_get_dispatch(self), on_group_private_message); |
132 | 1 | tox_events_callback_group_message(tox_node_get_dispatch(self), on_group_message); |
133 | 1 | tox_events_callback_group_invite(tox_node_get_dispatch(self), on_group_invite); |
134 | | |
135 | 1 | tox_node_log(self, "Waiting for TCP connection..."); |
136 | 1 | WAIT_UNTIL(tox_node_get_connection_status(self) == TOX_CONNECTION_TCP); |
137 | 1 | tox_node_log(self, "Connected. Waiting for Alice..."); |
138 | 1 | WAIT_UNTIL(tox_node_is_friend_connected(self, 0)); |
139 | 1 | if (!tox_node_is_friend_connected(self, 0)) { |
140 | 0 | tox_node_log(self, "TIMEOUT waiting for Alice."); |
141 | 0 | return; |
142 | 0 | } |
143 | 1 | tox_node_log(self, "Alice connected."); |
144 | | |
145 | 1 | tox_scenario_barrier_wait(self); // Barrier 1: Alice has chat_id |
146 | | |
147 | 1 | ToxScenario *s = tox_node_get_scenario(self); |
148 | 1 | ToxNode *alice_node = tox_scenario_get_node(s, 0); |
149 | 1 | State *alice_state = (State *)tox_node_get_script_ctx(alice_node); |
150 | | |
151 | 1 | tox_node_log(self, "Joining group via chat_id..."); |
152 | 1 | Tox_Err_Group_Join jerr; |
153 | 1 | state->group_number = tox_group_join(tox, alice_state->chat_id, (const uint8_t *)"test", 4, nullptr, 0, &jerr); |
154 | 1 | ck_assert(jerr == TOX_ERR_GROUP_JOIN_OK); |
155 | | |
156 | 1 | WAIT_UNTIL(state->got_private_message); |
157 | 1 | if (!state->got_private_message) { |
158 | 0 | return; |
159 | 0 | } |
160 | 1 | tox_scenario_barrier_wait(self); // Barrier 2: PM received, now leaving |
161 | | |
162 | 1 | Tox_Err_Group_Leave err_exit; |
163 | 1 | tox_group_leave(tox, state->group_number, nullptr, 0, &err_exit); |
164 | 1 | ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK); |
165 | | |
166 | 1 | state->got_invite = false; |
167 | 1 | tox_scenario_barrier_wait(self); // Barrier 3: Left, waiting for invite |
168 | 1 | WAIT_UNTIL(state->got_invite); |
169 | 1 | WAIT_UNTIL(state->got_group_message); |
170 | 1 | } |
171 | | |
172 | | static void relay_script(ToxNode *self, void *ctx) |
173 | 1 | { |
174 | 1 | (void)ctx; |
175 | 1 | tox_scenario_barrier_wait(self); // Barrier 1 |
176 | 1 | tox_scenario_barrier_wait(self); // Barrier 2 |
177 | 1 | tox_scenario_barrier_wait(self); // Barrier 3 |
178 | 1 | } |
179 | | |
180 | | int main(int argc, char **argv) |
181 | 1 | { |
182 | 1 | ToxScenario *s = tox_scenario_new(argc, argv, 120000); |
183 | | |
184 | 1 | struct Tox_Options *options_alice = tox_options_new(nullptr); |
185 | 1 | tox_options_set_udp_enabled(options_alice, false); |
186 | | |
187 | 1 | struct Tox_Options *options_bob = tox_options_new(nullptr); |
188 | 1 | tox_options_set_udp_enabled(options_bob, false); |
189 | | |
190 | 1 | struct Tox_Options *options_relay = tox_options_new(nullptr); |
191 | 1 | tox_options_set_tcp_port(options_relay, RELAY_TCP_PORT); |
192 | | |
193 | 1 | State *alice_state = (State *)calloc(1, sizeof(State)); |
194 | 1 | State *bob_state = (State *)calloc(1, sizeof(State)); |
195 | | |
196 | 1 | ToxNode *alice = tox_scenario_add_node_ex(s, "Alice", alice_script, alice_state, sizeof(State), options_alice); |
197 | 1 | ToxNode *bob = tox_scenario_add_node_ex(s, "Bob", bob_script, bob_state, sizeof(State), options_bob); |
198 | 1 | ToxNode *relay = tox_scenario_add_node_ex(s, "Relay", relay_script, nullptr, 0, options_relay); |
199 | | |
200 | 1 | tox_options_free(options_alice); |
201 | 1 | tox_options_free(options_bob); |
202 | 1 | tox_options_free(options_relay); |
203 | | |
204 | 1 | if (!alice || !bob || !relay) { |
205 | 0 | fprintf(stderr, "Failed to create nodes\n"); |
206 | 0 | return 1; |
207 | 0 | } |
208 | | |
209 | 1 | uint8_t relay_dht_id[TOX_PUBLIC_KEY_SIZE]; |
210 | 1 | tox_self_get_dht_id(tox_node_get_tox(relay), relay_dht_id); |
211 | | |
212 | 1 | uint16_t relay_tcp_port = tox_self_get_tcp_port(tox_node_get_tox(relay), nullptr); |
213 | | |
214 | 1 | Tox_Err_Bootstrap berr; |
215 | | |
216 | | // Both Alice and Bob use the Relay for TCP and DHT bootstrapping |
217 | 1 | tox_add_tcp_relay(tox_node_get_tox(alice), "127.0.0.1", relay_tcp_port, relay_dht_id, &berr); |
218 | 1 | tox_add_tcp_relay(tox_node_get_tox(bob), "127.0.0.1", relay_tcp_port, relay_dht_id, &berr); |
219 | | |
220 | 1 | tox_node_bootstrap(alice, relay); |
221 | 1 | tox_node_bootstrap(bob, relay); |
222 | | |
223 | 1 | tox_node_friend_add(alice, bob); |
224 | 1 | tox_node_friend_add(bob, alice); |
225 | | |
226 | 1 | ToxScenarioStatus res = tox_scenario_run(s); |
227 | 1 | tox_scenario_free(s); |
228 | 1 | free(alice_state); |
229 | 1 | free(bob_state); |
230 | | |
231 | 1 | return (res == TOX_SCENARIO_DONE) ? 0 : 1; |
232 | 1 | } |
233 | | |
234 | | #undef RELAY_TCP_PORT |