GNUnet debian-0.24.3-23-g589b01d60
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
45{
47 struct RecvState *rs;
49};
50
51
53{
55 uint32_t num_channels;
59};
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 ") %s\n",
129 GNUNET_ntohll (msg->id),
130 GNUNET_ntohll (msg->batch),
131 msg->node_id);
132
133 /* First, find the channel count struct with the channel over which we
134 * received this message */
135 channel_count = NULL;
136 channel_i = rs->num_channels; /* For error checking -
137 should be overwritten in the following loop. */
138 for (uint32_t i = 0; i<rs->num_channels; i++)
139 {
140 struct ChannelCount *channel_count_iter = &rs->channel_count[i];
141 if (NULL == channel_count_iter->channel)
142 {
143 channel_count = channel_count_iter;
144 channel_count->channel = channel;
145 channel_count->rs = rs;
146 channel_i = i;
147 break;
148 }
149 else if (channel == channel_count_iter->channel)
150 {
151 channel_count = channel_count_iter;
152 channel_i = i;
153 break;
154 }
155 // else: continue until suitable channel count structure is found
156 }
157 if (NULL == channel_count)
158 {
159 /* no suitable channel was found -> add this channel */
162 rs->num_channels + 1);
163 channel_count = &rs->channel_count[rs->num_channels - 1];
164 channel_count->channel = channel;
165 channel_count->rs = rs;
166 channel_i = rs->num_channels;
167 }
168
169 /* Then update number of received messages */
170 channel_count->num_messages_received++;
171
172 /* Finally check if this and then other channels received the correct amount
173 * potentially finish. */
175 num_messages_target = channel_count->rs->num_messages_target;
177 "Received %" PRIu64 " messages (of %" PRIu64 " on channel %" PRIu32 ")\n",
179 num_messages_target,
180 channel_i);
181 if (num_messages_target > num_messages_received) return;
182 if (num_messages_target < num_messages_received) GNUNET_assert (0);
183 //if (num_messages_target == num_messages_received)
184 // GNUNET_TESTING_async_finish (&rs->ac);
185 ret = GNUNET_YES;
186 for (uint32_t i = 0; i < rs->num_channels; i++)
187 {
188 channel_count = &rs->channel_count[i];
189 if (channel_count->num_messages_received != rs->num_messages_target)
190 ret = GNUNET_NO;
191 }
192 if (GNUNET_YES == ret)
193 {
194 LOG (GNUNET_ERROR_TYPE_INFO, "Received all expected messages on all channels\n");
196 // TODO do we want to keep track of this task?
197 /* If we finish this task, this ARM will shut down this peer, taking with
198 * it core and with it all the messages still in transit.
199 * Adding a bit of delay gives the other peer a chance to still receive
200 * them.
201 * This might be done nicer - via a barrier? Check the other node's receive
202 * state?
203 * The number of 3 Milliseconds was chosen by looking at logs and then
204 * continuously runnint the test and seeing how many actually work reliably
205 * (Increased it quite a bit in the end for valgrind - no repeated tests
206 * this time.)
207 */
211 rs);
212 }
213}
214
215
216static void
217exec_recv_run (void *cls,
219{
220 struct RecvState *rs = cls;
221 const struct GNUNET_TESTING_CORE_ConnectState *connect_state;
222
224 // TODO make the "connect" an input to the command
226 &connect_state)) {
227 GNUNET_assert (0);
228 };
229 rs->connect_state = connect_state;
230 // FIXME: set cls per hanlder
231 GNUNET_array_append (connect_state->recv_handlers,
232 connect_state->recv_handlers_len,
234 // FIXME is the following ok?
235 ((struct GNUNET_TESTING_CORE_ConnectState *)connect_state)->recv_handlers_cls = rs;
236}
237
238
239static void
241{
242 //struct RecvState *rs = cls;
243 // TODO
244
245 //GNUNET_free (rs->channel_count);
246 //GNUNET_free (rs);
247}
248
249
250const struct GNUNET_TESTING_Command
252 const char *label,
253 uint64_t num_messages)
254{
255 struct RecvState *rs;
256
257 // TODO this could be a static global variable
258 rs = GNUNET_new (struct RecvState);
259 rs->num_channels = 0;
261 rs->num_messages_target = num_messages;
262 LOG (GNUNET_ERROR_TYPE_DEBUG, "(Setting up _cmd_recv)\n");
264 rs, // state
265 label,
268 NULL, // traits
269 &rs->ac); // FIXME
270}
271
272
273/* 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.
Definition: common_endian.c:54
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
uint32_t num_channels
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)