GNUnet 0.25.0-2-g14b9b8ef2
 
Loading...
Searching...
No Matches
testing_core_cmd_recv.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2024 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_core_service.h"
32
33
37#define LOG(kind, ...) \
38 GNUNET_log_from (kind, "testing-core-recv", __VA_ARGS__)
39
40
41struct RecvState;
42
43
50
51
60
61
62static void
63handle_msg_test (void *cls,
64 struct GNUNET_TESTING_CORE_Channel *channel,
65 const struct GNUNET_TESTING_CORE_Message *msg);
66
67
68static void
70{
71 struct RecvState *rs = cls;
72
73 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finishing test delayed\n");
75 GNUNET_free (rs);
76}
77
78
79static void
81{
82 LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing recv handler\n");
83 for (uint64_t i = 0; i < connect_state->recv_handlers_len; i++)
84 {
86 {
87 // FIXME this is the dirty solution. The attempt below did for whatever
88 // reason not work.
90 // LOG (GNUNET_ERROR_TYPE_DEBUG,
91 // "recv handlers[0]: %p, handle_msg_test: %p, (%lu)\n",
92 // connect_state->recv_handlers[0],
93 // &handle_msg_test,
94 // sizeof (&handle_msg_test));
95 // LOG (GNUNET_ERROR_TYPE_DEBUG,
96 // "recv handlers: %p, %" PRIu64 "\n",
97 // connect_state->recv_handlers,
98 // connect_state->recv_handlers_len);
99 // GNUNET_memcpy (&connect_state->recv_handlers[i],
100 // &connect_state->recv_handlers[i+1],
101 // (connect_state->connect_cbs_len - i - 1) *
102 // sizeof (handle_msg_test));
103 // LOG (GNUNET_ERROR_TYPE_DEBUG,
104 // "recv handlers: %p, %" PRIu64 "\n",
105 // connect_state->recv_handlers,
106 // connect_state->recv_handlers_len);
107 // GNUNET_array_grow (connect_state->recv_handlers,
108 // connect_state->recv_handlers_len,
109 // connect_state->recv_handlers_len - 1);
110 }
111 }
112}
113
114
115static void
117 struct GNUNET_TESTING_CORE_Channel *channel,
118 const struct GNUNET_TESTING_CORE_Message *msg)
119{
120 // struct ChannelCount *channel_count = cls;
121 struct RecvState *rs = cls;
122 struct ChannelCount *channel_count;
123 uint32_t channel_i;
124 uint64_t num_messages_received;
125 uint64_t num_messages_target;
127
128 LOG (GNUNET_ERROR_TYPE_INFO, "received test message %" PRIu64 " (%" PRIu64
129 ") %s\n",
130 GNUNET_ntohll (msg->id),
131 GNUNET_ntohll (msg->batch),
132 msg->node_id);
133
134 /* First, find the channel count struct with the channel over which we
135 * received this message */
136 channel_count = NULL;
137 channel_i = rs->num_channels; /* For error checking -
138 should be overwritten in the following loop. */
139 for (uint32_t i = 0; i<rs->num_channels; i++)
140 {
141 struct ChannelCount *channel_count_iter = &rs->channel_count[i];
142 if (NULL == channel_count_iter->channel)
143 {
144 channel_count = channel_count_iter;
145 channel_count->channel = channel;
146 channel_count->rs = rs;
147 channel_i = i;
148 break;
149 }
150 else if (channel == channel_count_iter->channel)
151 {
152 channel_count = channel_count_iter;
153 channel_i = i;
154 break;
155 }
156 // else: continue until suitable channel count structure is found
157 }
158 if (NULL == channel_count)
159 {
160 /* no suitable channel was found -> add this channel */
163 rs->num_channels + 1);
164 channel_count = &rs->channel_count[rs->num_channels - 1];
165 channel_count->channel = channel;
166 channel_count->rs = rs;
167 channel_i = rs->num_channels;
168 }
169
170 /* Then update number of received messages */
171 channel_count->num_messages_received++;
172
173 /* Finally check if this and then other channels received the correct amount
174 * potentially finish. */
176 num_messages_target = channel_count->rs->num_messages_target;
178 "Received %" PRIu64 " messages (of %" PRIu64 " on channel %" PRIu32
179 ")\n",
181 num_messages_target,
182 channel_i);
183 if (num_messages_target > num_messages_received)
184 return;
185 if (num_messages_target < num_messages_received)
186 GNUNET_assert (0);
187 // if (num_messages_target == num_messages_received)
188 // GNUNET_TESTING_async_finish (&rs->ac);
189 ret = GNUNET_YES;
190 for (uint32_t i = 0; i < rs->num_channels; i++)
191 {
192 channel_count = &rs->channel_count[i];
193 if (channel_count->num_messages_received != rs->num_messages_target)
194 ret = GNUNET_NO;
195 }
196 if (GNUNET_YES == ret)
197 {
199 "Received all expected messages on all channels\n");
201 // TODO do we want to keep track of this task?
202 /* If we finish this task, this ARM will shut down this peer, taking with
203 * it core and with it all the messages still in transit.
204 * Adding a bit of delay gives the other peer a chance to still receive
205 * them.
206 * This might be done nicer - via a barrier? Check the other node's receive
207 * state?
208 * The number of 3 Milliseconds was chosen by looking at logs and then
209 * continuously running the test and seeing how many actually work reliably
210 * (Increased it quite a bit in the end for valgrind - no repeated tests
211 * this time.)
212 */
216 rs);
217 }
218}
219
220
221static void
222exec_recv_run (void *cls,
224{
225 struct RecvState *rs = cls;
226 const struct GNUNET_TESTING_CORE_ConnectState *connect_state;
227
229 // TODO make the "connect" an input to the command
231 &connect_state))
232 {
233 GNUNET_assert (0);
234 }
235 ;
236 rs->connect_state = connect_state;
237 // FIXME: set cls per handler
238 GNUNET_array_append (connect_state->recv_handlers,
239 connect_state->recv_handlers_len,
241 // FIXME is the following ok?
242 ((struct GNUNET_TESTING_CORE_ConnectState *) connect_state)->recv_handlers_cls
243 = rs;
244}
245
246
247static void
249{
250 // struct RecvState *rs = cls;
251 // TODO
252
253 // GNUNET_free (rs->channel_count);
254 // GNUNET_free (rs);
255}
256
257
258const struct GNUNET_TESTING_Command
260 const char *label,
261 uint64_t num_messages)
262{
263 struct RecvState *rs;
264
265 // TODO this could be a static global variable
266 rs = GNUNET_new (struct RecvState);
267 rs->num_channels = 0;
269 rs->num_messages_target = num_messages;
270 LOG (GNUNET_ERROR_TYPE_DEBUG, "(Setting up _cmd_recv)\n");
272 rs, // state
273 label,
276 NULL, // traits
277 &rs->ac); // FIXME
278}
279
280
281/* end of src/service/core/testing_core_recv.c */
struct GNUNET_MessageHeader * msg
Definition 005.c:2
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TESTING_Interpreter * is
Core service; the main API for encrypted P2P communications.
enum GNUNET_GenericReturnValue GNUNET_CORE_TESTING_get_trait_connect(const struct GNUNET_TESTING_Command *cmd, const struct GNUNET_TESTING_CORE_ConnectState **ret)
struct GNUNET_TESTING_Command GNUNET_TESTING_command_new_ac(void *cls, const char *label, GNUNET_TESTING_CommandRunRoutine run, GNUNET_TESTING_CommandCleanupRoutine cleanup, GNUNET_TESTING_CommandGetTraits traits, struct GNUNET_TESTING_AsyncContext *ac)
Create a new command that may be asynchronous.
void GNUNET_TESTING_async_finish(struct GNUNET_TESTING_AsyncContext *ac)
The asynchronous command of ac has finished.
const struct GNUNET_TESTING_Command * GNUNET_TESTING_interpreter_lookup_command(struct GNUNET_TESTING_Interpreter *is, const char *label)
Lookup command by label.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
uint64_t num_messages_received
struct GNUNET_TESTING_CORE_Channel * channel
struct RecvState * rs
State each asynchronous command must have in its closure.
GNUNET_TESTING_CORE_handle_msg * recv_handlers
Receive callback.
A command to be run by the interpreter.
struct GNUNET_TESTING_CommandLabel label
Label for the command.
Global state of the interpreter, used by a command to access information about other commands.
uint64_t num_messages_target
struct GNUNET_TESTING_CORE_ConnectState * connect_state
struct ChannelCount * channel_count
struct GNUNET_TESTING_AsyncContext ac
static void exec_recv_run(void *cls, struct GNUNET_TESTING_Interpreter *is)
static void exec_recv_cleanup(void *cls)
const struct GNUNET_TESTING_Command GNUNET_TESTING_CORE_cmd_recv(const char *label, uint64_t num_messages)
#define LOG(kind,...)
Generic logging shortcut.
static void handle_msg_test(void *cls, struct GNUNET_TESTING_CORE_Channel *channel, const struct GNUNET_TESTING_CORE_Message *msg)
static void remove_recv_handler(struct GNUNET_TESTING_CORE_ConnectState *connect_state)
static void do_finish_cmd_delayed(void *cls)