2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors)
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * @file psyc/test_psyc.c
23 * @brief Test for the PSYC service.
24 * @author Gabor X Toth
25 * @author Christian Grothoff
31 #include "gnunet_crypto_lib.h"
32 #include "gnunet_common.h"
33 #include "gnunet_util_lib.h"
34 #include "gnunet_testing_lib.h"
35 #include "gnunet_env_lib.h"
36 #include "gnunet_psyc_service.h"
38 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
40 #define DEBUG_SERVICE 0
44 * Return value from 'main'.
48 static const struct GNUNET_CONFIGURATION_Handle *cfg;
51 * Handle for task for timeout termination.
53 static GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
55 static struct GNUNET_PSYC_Master *mst;
56 static struct GNUNET_PSYC_Slave *slv;
57 static struct GNUNET_PSYC_Channel *ch;
59 static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
60 static struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key;
62 static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
63 static struct GNUNET_CRYPTO_EddsaPublicKey slave_pub_key;
65 struct GNUNET_PSYC_MasterTransmitHandle *mth;
67 struct TransmitClosure
69 struct GNUNET_PSYC_MasterTransmitHandle *handle;
70 struct GNUNET_ENV_Environment *env;
72 const char *mod_value;
73 size_t mod_value_size;
79 struct TransmitClosure *tmit;
82 * Clean up all resources used.
89 GNUNET_PSYC_master_stop (mst);
94 GNUNET_ENV_environment_destroy (tmit->env);
98 GNUNET_SCHEDULER_shutdown ();
103 * Terminate the testcase (failure).
106 * @param tc scheduler context
109 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
117 * Terminate the testcase (success).
120 * @param tc scheduler context
123 end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
131 * Finish the testcase (successfully).
136 if (end_badly_task != GNUNET_SCHEDULER_NO_TASK)
138 GNUNET_SCHEDULER_cancel (end_badly_task);
139 end_badly_task = GNUNET_SCHEDULER_NO_TASK;
141 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
142 &end_normally, NULL);
147 message (void *cls, uint64_t message_id, uint32_t flags,
148 const struct GNUNET_MessageHeader *msg)
152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
153 "Error while receiving message %llu\n", message_id);
157 uint16_t type = ntohs (msg->type);
158 uint16_t size = ntohs (msg->size);
160 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
161 "Got message part of type %u and size %u "
162 "belonging to message ID %llu with flags %u\n",
163 type, size, message_id, flags);
165 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type)
171 join_request (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key,
172 const char *method_name,
173 size_t variable_count, const struct GNUNET_ENV_Modifier *variables,
174 const void *data, size_t data_size,
175 struct GNUNET_PSYC_JoinHandle *jh)
177 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
178 "Got join request.");
183 transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
186 struct TransmitClosure *tmit = cls;
187 tmit->paused = GNUNET_NO;
188 GNUNET_PSYC_master_transmit_resume (tmit->handle);
193 tmit_notify_mod (void *cls, uint16_t *data_size, void *data, uint8_t *oper)
195 struct TransmitClosure *tmit = cls;
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Transmit notify modifier: %lu bytes available, "
198 "%u modifiers left to process.\n",
199 *data_size, GNUNET_ENV_environment_get_count (tmit->env));
201 enum GNUNET_ENV_Operator op = 0;
202 const char *name = NULL;
203 const char *value = NULL;
204 uint16_t name_size = 0;
205 size_t value_size = 0;
207 if (NULL != tmit->mod_value && 0 < tmit->mod_value_size)
208 { /* Modifier continuation */
209 value = tmit->mod_value;
210 if (tmit->mod_value_size <= *data_size)
212 value_size = tmit->mod_value_size;
213 tmit->mod_value = NULL;
217 value_size = *data_size;
218 tmit->mod_value += value_size;
220 tmit->mod_value_size -= value_size;
222 if (*data_size < value_size)
224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 "value larger than buffer: %u < %zu\n",
226 *data_size, value_size);
231 *data_size = value_size;
232 memcpy (data, value, value_size);
234 else if (NULL != oper)
236 if (GNUNET_NO == GNUNET_ENV_environment_shift (tmit->env, &op, &name,
237 (void *) &value, &value_size))
238 { /* No more modifiers, continue with data */
244 name_size = strlen (name);
246 if (name_size + 1 + value_size <= *data_size)
248 *data_size = name_size + 1 + value_size;
252 tmit->mod_value_size = value_size;
253 value_size = *data_size - name_size - 1;
254 tmit->mod_value_size -= value_size;
255 tmit->mod_value = value + value_size;
258 memcpy (data, name, name_size);
259 ((char *)data)[name_size] = '\0';
260 memcpy ((char *)data + name_size + 1, value, value_size);
263 return 0 == tmit->mod_value_size ? GNUNET_YES : GNUNET_NO;
268 tmit_notify_data (void *cls, uint16_t *data_size, void *data)
270 struct TransmitClosure *tmit = cls;
271 uint16_t size = strlen (tmit->data[tmit->n]);
272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
273 "Transmit notify data: %lu bytes available, "
274 "processing fragment %u/%u (size %u).\n",
275 *data_size, tmit->n + 1, tmit->data_count, size);
276 if (*data_size < size)
280 return GNUNET_SYSERR;
283 if (GNUNET_YES == tmit->paused && tmit->n == tmit->data_count - 1)
285 /* Send last fragment later. */
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
287 tmit->paused = GNUNET_YES;
288 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
289 (GNUNET_TIME_UNIT_SECONDS, 3),
290 &transmit_resume, tmit);
296 memcpy (data, tmit->data[tmit->n], size);
298 return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
303 master_started (void *cls, uint64_t max_message_id)
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
306 "Master started: %" PRIu64 "\n", max_message_id);
308 tmit = GNUNET_new (struct TransmitClosure);
309 tmit->env = GNUNET_ENV_environment_create ();
310 GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN,
311 "_foo", "bar baz", 7);
312 GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN,
313 "_foo_bar", "foo bar baz", 11);
314 tmit->data[0] = "foo";
315 tmit->data[1] = "foo bar";
316 tmit->data[2] = "foo bar baz";
317 tmit->data_count = 3;
319 = GNUNET_PSYC_master_transmit (mst, "_test", tmit_notify_mod,
320 tmit_notify_data, tmit,
321 GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN);
326 slave_joined (void *cls, uint64_t max_message_id)
328 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave joined: %lu\n", max_message_id);
333 * Main function of the test, run from scheduler.
336 * @param cfg configuration we use (also to connect to PSYC service)
337 * @param peer handle to access more of the peer (not used)
341 run (void *cls, char *const *args, const char *cfgfile,
342 const struct GNUNET_CONFIGURATION_Handle *c)
345 const struct GNUNET_CONFIGURATION_Handle *c,
346 struct GNUNET_TESTING_Peer *peer)
350 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
352 channel_key = GNUNET_CRYPTO_eddsa_key_create ();
353 slave_key = GNUNET_CRYPTO_eddsa_key_create ();
355 GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
356 GNUNET_CRYPTO_eddsa_key_get_public (slave_key, &slave_pub_key);
358 mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE,
359 &message, &join_request, &master_started, NULL);
360 return; /* FIXME: test slave */
362 struct GNUNET_PeerIdentity origin;
363 struct GNUNET_PeerIdentity relays[16];
364 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
365 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN,
366 "_foo", "bar baz", 7);
367 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN,
368 "_foo_bar", "foo bar baz", 11);
369 slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, &origin,
370 16, relays, &message, &join_request, &slave_joined,
371 NULL, "_request_join", env, "some data", 9);
372 GNUNET_ENV_environment_destroy (env);
377 main (int argc, char *argv[])
381 const struct GNUNET_GETOPT_CommandLineOption opts[] = {
382 GNUNET_GETOPT_OPTION_END
384 if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psyc",
385 "test-psyc [options]",
389 if (0 != GNUNET_TESTING_peer_run ("test-psyc", "test_psyc.conf", &run, NULL))
395 /* end of test_psyc.c */