2 This file is part of GNUnet.
3 Copyright (C) 2019 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/transport-testing2.c
23 * @brief functions related to testing-tng
24 * @author Christian Grothoff
25 * @author Julius Bünger
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_constants.h"
31 #include "transport-testing2.h"
32 #include "gnunet_ats_transport_service.h"
33 #include "gnunet_hello_lib.h"
34 #include "gnunet_signatures.h"
35 #include "transport.h"
38 #define LOG(kind,...) GNUNET_log_from (kind, "transport-testing2", __VA_ARGS__)
41 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
44 * @brief Handle to the configuration
46 struct GNUNET_CONFIGURATION_Handle *cfg;
49 * @brief File name of configuration file
54 * @brief Handle to the transport service
56 struct GNUNET_SERVICE_Handle *tsh;
59 * @brief Task that will be run on shutdown to stop and clean transport
62 struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
65 * @brief Handle to the client
67 struct GNUNET_SERVICE_Client *client;
70 * @brief Handle to the client
72 struct GNUNET_MQ_Handle *c_mq;
75 * @brief Process of the communicator
77 struct GNUNET_OS_Process *c_proc;
80 * @brief Task that will be run on shutdown to stop and clean communicator
82 struct GNUNET_SCHEDULER_Task *c_shutdown_task;
85 * @brief Characteristics of the communicator
87 enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
90 * @brief Specifies supported addresses
95 * @brief Specifies supported addresses
100 * @brief Head of the queues
102 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
105 * @brief Tail of the queues
107 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
109 /* Callbacks + Closures */
111 * @brief Callback called when a new communicator connects
113 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback communicator_available_cb;
116 * @brief Callback called when a new communicator connects
118 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
121 * @brief Callback called when a new communicator connects
123 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
126 * @brief Callback called when a new communicator connects
128 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
131 * @brief Closure to the callback
137 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue
140 * @brief Handle to the TransportCommunicator
142 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
145 * @brief Task to request the opening of a view
147 struct GNUNET_MQ_Envelope *open_queue_env;
150 * @brief Peer ID of the peer on the other side of the queue
152 struct GNUNET_PeerIdentity peer_id;
160 * @brief Current message id
165 * An `enum GNUNET_NetworkType` in NBO.
170 * Maximum transmission unit, in NBO. UINT32_MAX for unlimited.
175 * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
180 * @brief Next element inside a DLL
182 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next;
185 * @brief Previous element inside a DLL
187 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev;
191 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission
197 * @brief Check whether incoming msg indicating available communicator is
201 * @param msg Message struct
203 * @return GNUNET_YES in case message is correct
206 check_communicator_available (void *cls,
207 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
211 size = ntohs (msg->header.size) - sizeof (*msg);
213 return GNUNET_OK; /* receive-only communicator */
214 GNUNET_MQ_check_zero_termination (msg);
220 * @brief Handle new communicator
223 * @param msg Message struct
226 handle_communicator_available (void *cls,
227 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
229 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
232 size = ntohs (msg->header.size) - sizeof (*msg);
234 return; /* receive-only communicator */
235 tc_h->c_characteristics = ntohl (msg->cc);
236 tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]);
237 if (NULL != tc_h->communicator_available_cb)
239 LOG (GNUNET_ERROR_TYPE_DEBUG,
240 "calling communicator_available_cb()\n");
241 tc_h->communicator_available_cb (tc_h->cb_cls,
243 tc_h->c_characteristics,
244 tc_h->c_addr_prefix);
246 GNUNET_SERVICE_client_continue (tc_h->client);
251 * Address of our peer added. Test message is well-formed.
253 * @param cls the client
254 * @param aam the send message that was sent
255 * @return #GNUNET_OK if message is well-formed
258 check_add_address (void *cls,
259 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
261 struct TransportClient *tc = cls;
263 //if (CT_COMMUNICATOR != tc->type)
266 // return GNUNET_SYSERR;
268 GNUNET_MQ_check_zero_termination (msg);
274 handle_add_address (void *cls,
275 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
277 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
280 size = ntohs (msg->header.size) - sizeof (*msg);
282 return; /* receive-only communicator */
283 tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]);
284 if (NULL != tc_h->add_address_cb)
286 LOG (GNUNET_ERROR_TYPE_DEBUG,
287 "calling communicator_available()\n");
288 tc_h->add_address_cb (tc_h->cb_cls,
291 GNUNET_TIME_relative_ntoh (msg->expiration),
295 GNUNET_SERVICE_client_continue (tc_h->client);
300 handle_queue_create_ok (void *cls,
301 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
303 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
305 if (NULL != tc_h->queue_create_reply_cb)
307 tc_h->queue_create_reply_cb (tc_h->cb_cls,
311 GNUNET_SERVICE_client_continue (tc_h->client);
316 handle_queue_create_fail (void *cls,
317 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
319 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
321 if (NULL != tc_h->queue_create_reply_cb)
323 tc_h->queue_create_reply_cb (tc_h->cb_cls,
327 GNUNET_SERVICE_client_continue (tc_h->client);
332 * New queue became available. Check message.
334 * @param cls the client
335 * @param aqm the send message that was sent
338 check_add_queue_message (void *cls,
339 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
341 GNUNET_MQ_check_zero_termination (aqm);
347 * @brief Handle new communicator
350 * @param msg Message struct
353 handle_add_queue_message (void *cls,
354 const struct GNUNET_TRANSPORT_AddQueueMessage *msg)
356 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
357 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
359 tc_queue = tc_h->queue_head;
360 while (tc_queue->qid != msg->qid)
362 tc_queue = tc_queue->next;
364 GNUNET_assert (tc_queue->qid == msg->qid);
365 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id,
367 tc_queue->nt = msg->nt;
368 tc_queue->mtu = msg->mtu;
369 tc_queue->cs = msg->cs;
370 if (NULL != tc_h->add_queue_cb)
372 tc_h->add_queue_cb (tc_h->cb_cls,
376 GNUNET_SERVICE_client_continue (tc_h->client);
381 * @brief Shut down the service
383 * @param cls Closure - Handle to the service
386 shutdown_service (void *cls)
388 struct GNUNET_SERVICE_Handle *h = cls;
390 GNUNET_SERVICE_stop (h);
395 * @brief Callback called when new Client (Communicator) connects
397 * @param cls Closure - TransporCommmunicator Handle
398 * @param client Client
399 * @param mq Messagequeue
401 * @return TransportCommunicator Handle
404 connect_cb (void *cls,
405 struct GNUNET_SERVICE_Client *client,
406 struct GNUNET_MQ_Handle *mq)
408 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
409 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter;
411 LOG (GNUNET_ERROR_TYPE_DEBUG,
412 "Client connected.\n");
413 tc_h->client = client;
416 if (NULL == tc_h->queue_head) return tc_h;
417 while (NULL != (tc_queue_iter = tc_h->queue_head))
419 if (NULL == tc_queue_iter->open_queue_env) continue;
420 GNUNET_MQ_send (tc_h->c_mq,
421 tc_queue_iter->open_queue_env);
422 tc_queue_iter->open_queue_env = NULL;
429 * @brief Callback called when Client disconnects
431 * @param cls Closure - TransportCommunicator Handle
432 * @param client Client
433 * @param internal_cls TransporCommmunicator Handle
436 disconnect_cb (void *cls,
437 struct GNUNET_SERVICE_Client *client,
440 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
442 LOG (GNUNET_ERROR_TYPE_DEBUG,
443 "Client disconnected.\n");
449 * @brief Start the communicator part of the transport service
451 * @param communicator_available Callback to be called when a new communicator
453 * @param cfg Configuration
456 transport_communicator_start (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
458 struct GNUNET_MQ_MessageHandler mh[] = {
459 GNUNET_MQ_hd_var_size (communicator_available,
460 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
461 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
463 //GNUNET_MQ_hd_var_size (communicator_backchannel,
464 // GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
465 // struct GNUNET_TRANSPORT_CommunicatorBackchannel,
467 GNUNET_MQ_hd_var_size (add_address,
468 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
469 struct GNUNET_TRANSPORT_AddAddressMessage,
471 //GNUNET_MQ_hd_fixed_size (del_address,
472 // GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
473 // struct GNUNET_TRANSPORT_DelAddressMessage,
475 //GNUNET_MQ_hd_var_size (incoming_msg,
476 // GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
477 // struct GNUNET_TRANSPORT_IncomingMessage,
479 GNUNET_MQ_hd_fixed_size (queue_create_ok,
480 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
481 struct GNUNET_TRANSPORT_CreateQueueResponse,
483 GNUNET_MQ_hd_fixed_size (queue_create_fail,
484 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
485 struct GNUNET_TRANSPORT_CreateQueueResponse,
487 GNUNET_MQ_hd_var_size (add_queue_message,
488 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
489 struct GNUNET_TRANSPORT_AddQueueMessage,
491 //GNUNET_MQ_hd_fixed_size (del_queue_message,
492 // GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
493 // struct GNUNET_TRANSPORT_DelQueueMessage,
495 //GNUNET_MQ_hd_fixed_size (send_message_ack,
496 // GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
497 // struct GNUNET_TRANSPORT_SendMessageToAck,
500 struct GNUNET_SERVICE_Handle *h;
502 h = GNUNET_SERVICE_start ("transport",
509 LOG (GNUNET_ERROR_TYPE_ERROR,
510 "Failed starting service!\n");
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Started service\n");
515 /* TODO */ GNUNET_SCHEDULER_add_shutdown (&shutdown_service, h);
521 * @brief Task run at shutdown to kill communicator and clean up
523 * @param cls Closure - Process of communicator
526 shutdown_communicator (void *cls)
528 struct GNUNET_OS_Process *proc = cls;
530 if (GNUNET_OK != GNUNET_OS_process_kill (proc,
533 LOG (GNUNET_ERROR_TYPE_WARNING,
534 "Error shutting down communicator with SIGERM, trying SIGKILL\n");
535 if (GNUNET_OK != GNUNET_OS_process_kill (proc,
538 LOG (GNUNET_ERROR_TYPE_ERROR,
539 "Error shutting down communicator with SIGERM and SIGKILL\n");
542 GNUNET_OS_process_destroy (proc);
547 * @brief Start the communicator
549 * @param cfgname Name of the communicator
552 communicator_start (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "communicator_start\n");
558 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-communicator-unix");
560 GNUNET_OS_start_process (GNUNET_YES,
561 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
564 "./gnunet-communicator-unix",
568 if (NULL == tc_h->c_proc)
570 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
571 "Failed to start communicator!");
574 LOG (GNUNET_ERROR_TYPE_DEBUG,
575 "started communicator\n");
576 GNUNET_free (binary);
577 /* TODO */ GNUNET_SCHEDULER_add_shutdown (&shutdown_communicator,
583 * @brief Start communicator part of transport service and communicator
585 * @param service_name Name of the service
586 * @param cfg Configuration handle
587 * @param communicator_available_cb Callback that is called when a new
588 * @param add_address_cb Callback that is called when a new
589 * communicator becomes available
590 * @param cb_cls Closure to @a communicator_available_cb and @a
592 * @return Handle to the communicator duo
594 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
595 GNUNET_TRANSPORT_TESTING_transport_communicator_service_start
596 (const char *service_name,
597 const char *cfg_filename,
598 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback communicator_available_cb,
599 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb,
600 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb,
601 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb,
604 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
606 tc_h = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle);
607 tc_h->cfg_filename = GNUNET_strdup (cfg_filename);
608 tc_h->cfg = GNUNET_CONFIGURATION_create ();
609 if ( (GNUNET_SYSERR ==
610 GNUNET_CONFIGURATION_load (tc_h->cfg,
613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
614 _("Malformed configuration file `%s', exit ...\n"),
618 tc_h->communicator_available_cb = communicator_available_cb;
619 tc_h->add_address_cb = add_address_cb;
620 tc_h->queue_create_reply_cb = queue_create_reply_cb;
621 tc_h->add_queue_cb = add_queue_cb;
622 tc_h->cb_cls = cb_cls;
624 /* Start communicator part of service */
625 transport_communicator_start (tc_h);
627 /* Schedule start communicator */
628 communicator_start (tc_h);
634 GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue
635 (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
636 const struct GNUNET_PeerIdentity *peer_id,
639 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
640 static uint32_t idgen;
642 struct GNUNET_TRANSPORT_CreateQueue *msg;
643 struct GNUNET_MQ_Envelope *env;
646 tc_queue = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
647 prefix = GNUNET_HELLO_address_to_prefix (address);
650 GNUNET_break (0); /* We got an invalid address!? */
653 alen = strlen (address) + 1;
654 env = GNUNET_MQ_msg_extra (msg,
656 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
657 msg->request_id = htonl (idgen++);
658 tc_queue->qid = msg->request_id;
659 msg->receiver = *peer_id;
660 tc_queue->peer_id = *peer_id;
664 if (NULL != tc_h->c_mq)
666 GNUNET_MQ_send (tc_h->c_mq,
671 tc_queue->open_queue_env = env;
673 GNUNET_CONTAINER_DLL_insert (tc_h->queue_head,
679 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission *
680 GNUNET_TRANSPORT_TESTING_transport_communicator_send
681 (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue,
683 size_t payload_size/*,
684 GNUNET_TRANSPORT_TESTING_SuccessStatus cb,
687 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission *tc_t;
688 struct GNUNET_TRANSPORT_SendMessageTo *msg;
689 struct GNUNET_MQ_Envelope *env;
691 env = GNUNET_MQ_msg_extra (msg,
693 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
694 msg->qid = htonl (tc_queue->qid);
695 msg->mid = tc_queue->mid++;
696 msg->receiver = tc_queue->peer_id;
700 GNUNET_MQ_send (tc_queue->tc_h->c_mq,