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__)
42 struct MyClient *prev;
43 struct MyClient *next;
45 * @brief Handle to the client
47 struct GNUNET_SERVICE_Client *client;
50 * @brief Handle to the client
52 struct GNUNET_MQ_Handle *c_mq;
57 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc;
62 * @brief Handle to a transport communicator
64 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
69 struct MyClient *client_head;
70 struct MyClient *client_tail;
73 * @brief Handle to the client
75 struct GNUNET_MQ_Handle *c_mq;
78 * @brief Handle to the configuration
80 struct GNUNET_CONFIGURATION_Handle *cfg;
83 * @brief File name of configuration file
87 struct GNUNET_PeerIdentity peer_id;
90 * @brief Handle to the transport service
92 struct GNUNET_SERVICE_Handle *tsh;
95 * @brief Task that will be run on shutdown to stop and clean transport
98 struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
102 * @brief Process of the communicator
104 struct GNUNET_OS_Process *c_proc;
109 struct GNUNET_OS_Process *nat_proc;
112 * @brief Task that will be run on shutdown to stop and clean communicator
114 struct GNUNET_SCHEDULER_Task *c_shutdown_task;
117 * @brief Characteristics of the communicator
119 enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
122 * @brief Specifies supported addresses
127 * @brief Specifies supported addresses
132 * @brief Head of the DLL of queues associated with this communicator
134 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
137 * @brief Tail of the DLL of queues associated with this communicator
139 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
141 /* Callbacks + Closures */
143 * @brief Callback called when a new communicator connects
145 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
146 communicator_available_cb;
149 * @brief Callback called when a new communicator connects
151 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
154 * @brief Callback called when a new communicator connects
156 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
159 * @brief Callback called when a new communicator connects
161 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
164 * @brief Callback called when a new communicator connects
166 GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb;
169 * @brief Backchannel callback
171 GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb;
176 struct GNUNET_SERVICE_Handle *sh;
179 * @brief Closure to the callback
184 * Backchannel supported
191 * @brief Queue of a communicator and some context
193 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue
196 * @brief Handle to the TransportCommunicator
198 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
201 * @brief Envelope to a message that requests the opening of the queue.
203 * If the client already requests queue(s), but the communicator is not yet
204 * connected, we cannot send the request to open the queue. Save it until the
205 * communicator becomes available and send it then.
207 struct GNUNET_MQ_Envelope *open_queue_env;
210 * @brief Peer ID of the peer on the other side of the queue
212 struct GNUNET_PeerIdentity peer_id;
220 * @brief Current message id
225 * An `enum GNUNET_NetworkType` in NBO.
230 * Maximum transmission unit. UINT32_MAX for unlimited.
235 * Queue length. UINT64_MAX for unlimited.
245 * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
250 * @brief Next element inside a DLL
252 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next;
255 * @brief Previous element inside a DLL
257 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev;
262 * @brief Handle/Context to a single transmission
264 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission
270 * @brief Check whether incoming msg indicating available communicator is
274 * @param msg Message struct
276 * @return GNUNET_YES in case message is correct
279 check_communicator_available (
281 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
285 size = ntohs (msg->header.size) - sizeof(*msg);
287 return GNUNET_OK; /* receive-only communicator */
288 GNUNET_MQ_check_zero_termination (msg);
294 * @brief Handle new communicator
296 * Store characteristics of communicator, call respective client callback.
298 * @param cls Closure - communicator handle
299 * @param msg Message struct
302 handle_communicator_available (
304 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
306 struct MyClient *client = cls;
307 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
310 tc_h->c_mq = client->c_mq;
312 size = ntohs (msg->header.size) - sizeof(*msg);
315 GNUNET_SERVICE_client_continue (client->client);
316 return; /* receive-only communicator */
318 tc_h->c_characteristics = ntohl (msg->cc);
319 tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]);
320 if (NULL != tc_h->communicator_available_cb)
322 LOG (GNUNET_ERROR_TYPE_DEBUG, "calling communicator_available_cb()\n");
323 tc_h->communicator_available_cb (tc_h->cb_cls,
325 tc_h->c_characteristics,
326 tc_h->c_addr_prefix);
328 GNUNET_SERVICE_client_continue (client->client);
329 LOG (GNUNET_ERROR_TYPE_DEBUG, "finished communicator_available_cb()\n");
335 * Incoming message. Test message is well-formed.
337 * @param cls the client
338 * @param msg the send message that was sent
339 * @return #GNUNET_OK if message is well-formed
342 check_communicator_backchannel (void *cls,
344 GNUNET_TRANSPORT_CommunicatorBackchannel *msg)
346 // struct TransportClient *tc = cls;
348 // if (CT_COMMUNICATOR != tc->type)
351 // return GNUNET_SYSERR;
353 // GNUNET_MQ_check_boxed_message (msg);
359 * @brief Receive an incoming message.
361 * Pass the message to the client.
363 * @param cls Closure - communicator handle
367 handle_communicator_backchannel (void *cls,
369 GNUNET_TRANSPORT_CommunicatorBackchannel *
372 struct MyClient *client = cls;
373 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
375 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *other_tc_h;
376 struct GNUNET_MessageHeader *msg;
377 msg = (struct GNUNET_MessageHeader *) &bc_msg[1];
378 uint16_t isize = ntohs (msg->size);
379 const char *target_communicator = ((const char *) msg) + isize;
380 struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
381 struct GNUNET_MQ_Envelope *env;
383 LOG (GNUNET_ERROR_TYPE_DEBUG,
384 "Received backchannel message\n");
385 if (tc_h->bc_enabled != GNUNET_YES)
387 GNUNET_SERVICE_client_continue (client->client);
390 /* Find client providing this communicator */
391 /* Finally, deliver backchannel message to communicator */
392 LOG (GNUNET_ERROR_TYPE_DEBUG,
393 "Delivering backchannel message of type %u to %s\n",
395 target_communicator);
396 other_tc_h = tc_h->bc_cb (tc_h, msg, (struct
397 GNUNET_PeerIdentity*) &bc_msg->pid);
398 env = GNUNET_MQ_msg_extra (
401 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
402 cbi->pid = tc_h->peer_id;
403 memcpy (&cbi[1], msg, isize);
406 GNUNET_MQ_send (other_tc_h->c_mq, env);
407 GNUNET_SERVICE_client_continue (client->client);
412 * Address of our peer added. Test message is well-formed.
414 * @param cls the client
415 * @param aam the send message that was sent
416 * @return #GNUNET_OK if message is well-formed
419 check_add_address (void *cls,
420 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
422 // if (CT_COMMUNICATOR != tc->type)
425 // return GNUNET_SYSERR;
427 GNUNET_MQ_check_zero_termination (msg);
433 * @brief The communicator informs about an address.
435 * Store address and call client callback.
437 * @param cls Closure - communicator handle
441 handle_add_address (void *cls,
442 const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
444 struct MyClient *client = cls;
445 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
448 size = ntohs (msg->header.size) - sizeof(*msg);
450 return; /* receive-only communicator */
451 LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size);
452 tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]);
453 if (NULL != tc_h->add_address_cb)
455 LOG (GNUNET_ERROR_TYPE_DEBUG, "calling add_address_cb()\n");
456 tc_h->add_address_cb (tc_h->cb_cls,
459 GNUNET_TIME_relative_ntoh (msg->expiration),
463 GNUNET_SERVICE_client_continue (client->client);
468 * Incoming message. Test message is well-formed.
470 * @param cls the client
471 * @param msg the send message that was sent
472 * @return #GNUNET_OK if message is well-formed
475 check_incoming_msg (void *cls,
476 const struct GNUNET_TRANSPORT_IncomingMessage *msg)
478 // struct TransportClient *tc = cls;
480 // if (CT_COMMUNICATOR != tc->type)
483 // return GNUNET_SYSERR;
485 GNUNET_MQ_check_boxed_message (msg);
491 * @brief Receive an incoming message.
493 * Pass the message to the client.
495 * @param cls Closure - communicator handle
499 handle_incoming_msg (void *cls,
500 const struct GNUNET_TRANSPORT_IncomingMessage *inc_msg)
502 struct MyClient *client = cls;
503 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
505 struct GNUNET_MessageHeader *msg;
506 msg = (struct GNUNET_MessageHeader *) &inc_msg[1];
507 size_t payload_len = ntohs (msg->size) - sizeof (struct
508 GNUNET_MessageHeader);
509 if (NULL != tc_h->incoming_msg_cb)
511 tc_h->incoming_msg_cb (tc_h->cb_cls,
518 LOG (GNUNET_ERROR_TYPE_WARNING,
519 "Incoming message from communicator but no handler!\n");
521 if (GNUNET_YES == ntohl (inc_msg->fc_on))
523 /* send ACK when done to communicator for flow control! */
524 struct GNUNET_MQ_Envelope *env;
525 struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
527 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK);
528 GNUNET_assert (NULL != env);
529 ack->reserved = htonl (0);
530 ack->fc_id = inc_msg->fc_id;
531 ack->sender = inc_msg->sender;
532 GNUNET_MQ_send (tc_h->c_mq, env);
535 GNUNET_SERVICE_client_continue (client->client);
540 * @brief Communicator informs that it tries to establish requested queue
542 * @param cls Closure - communicator handle
546 handle_queue_create_ok (void *cls,
547 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
549 struct MyClient *client = cls;
550 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
553 if (NULL != tc_h->queue_create_reply_cb)
555 tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_YES);
557 GNUNET_SERVICE_client_continue (client->client);
562 * @brief Communicator informs that it wont try establishing requested queue.
564 * It will not do so probably because the address is bougus (see comment to
565 * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL)
567 * @param cls Closure - communicator handle
571 handle_queue_create_fail (
573 const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
575 struct MyClient *client = cls;
576 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
579 if (NULL != tc_h->queue_create_reply_cb)
581 tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_NO);
583 GNUNET_SERVICE_client_continue (client->client);
588 * New queue became available. Check message.
590 * @param cls the client
591 * @param aqm the send message that was sent
594 check_add_queue_message (void *cls,
595 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
597 GNUNET_MQ_check_zero_termination (aqm);
603 * @brief Handle new queue
605 * Store context and call client callback.
607 * @param cls Closure - communicator handle
608 * @param msg Message struct
611 handle_add_queue_message (void *cls,
612 const struct GNUNET_TRANSPORT_AddQueueMessage *msg)
614 struct MyClient *client = cls;
615 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
617 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
619 LOG (GNUNET_ERROR_TYPE_DEBUG,
620 "Got queue with ID %u\n", msg->qid);
621 for (tc_queue = tc_h->queue_head; NULL != tc_queue; tc_queue = tc_queue->next)
623 if (tc_queue->qid == msg->qid)
626 if (NULL == tc_queue)
629 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
630 tc_queue->tc_h = tc_h;
631 tc_queue->qid = msg->qid;
632 tc_queue->peer_id = msg->receiver;
633 GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
635 GNUNET_assert (tc_queue->qid == msg->qid);
636 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
637 tc_queue->nt = msg->nt;
638 tc_queue->mtu = ntohl (msg->mtu);
639 tc_queue->cs = msg->cs;
640 tc_queue->priority = ntohl (msg->priority);
641 tc_queue->q_len = GNUNET_ntohll (msg->q_len);
642 if (NULL != tc_h->add_queue_cb)
644 tc_h->add_queue_cb (tc_h->cb_cls, tc_h, tc_queue, tc_queue->mtu);
646 GNUNET_SERVICE_client_continue (client->client);
651 * @brief Handle new queue
653 * Store context and call client callback.
655 * @param cls Closure - communicator handle
656 * @param msg Message struct
659 handle_update_queue_message (void *cls,
661 GNUNET_TRANSPORT_UpdateQueueMessage *msg)
663 struct MyClient *client = cls;
664 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h =
666 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Received queue update message for %u with q_len %"PRIu64"\n",
670 msg->qid, GNUNET_ntohll(msg->q_len));
671 tc_queue = tc_h->queue_head;
672 if (NULL != tc_queue)
674 while (tc_queue->qid != msg->qid)
676 tc_queue = tc_queue->next;
679 GNUNET_assert (tc_queue->qid == msg->qid);
680 GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
681 tc_queue->nt = msg->nt;
682 tc_queue->mtu = ntohl (msg->mtu);
683 tc_queue->cs = msg->cs;
684 tc_queue->priority = ntohl (msg->priority);
685 tc_queue->q_len += GNUNET_ntohll (msg->q_len);
686 GNUNET_SERVICE_client_continue (client->client);
691 * @brief Shut down the service
693 * @param cls Closure - Handle to the service
696 shutdown_service (void *cls)
698 struct GNUNET_SERVICE_Handle *h = cls;
700 GNUNET_SERVICE_stop (h);
705 * @brief Callback called when new Client (Communicator) connects
707 * @param cls Closure - TransporCommmunicator Handle
708 * @param client Client
709 * @param mq Messagequeue
711 * @return TransportCommunicator Handle
714 connect_cb (void *cls,
715 struct GNUNET_SERVICE_Client *client,
716 struct GNUNET_MQ_Handle *mq)
718 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
719 struct MyClient *new_c;
721 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected to %p.\n",
723 new_c = GNUNET_new (struct MyClient);
724 new_c->client = client;
727 GNUNET_CONTAINER_DLL_insert (tc_h->client_head,
731 if (NULL == tc_h->queue_head)
733 /* Iterate over queues. They are yet to be opened. Request opening. */
735 GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter =
737 NULL != tc_queue_iter;
738 tc_queue_iter = tc_queue_iter->next)
740 if (NULL == tc_queue_iter->open_queue_env)
742 /* Send the previously created mq envelope to request the creation of the
744 GNUNET_MQ_send (tc_h->c_mq,
745 tc_queue_iter->open_queue_env);
746 tc_queue_iter->open_queue_env = NULL;
753 * @brief Callback called when Client disconnects
755 * @param cls Closure - TransportCommunicator Handle
756 * @param client Client
757 * @param internal_cls TransporCommmunicator Handle
760 disconnect_cb (void *cls,
761 struct GNUNET_SERVICE_Client *client,
764 struct MyClient *cl = cls;
765 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
767 for (cl = tc_h->client_head; NULL != cl; cl = cl->next)
769 if (cl->client != client)
771 GNUNET_CONTAINER_DLL_remove (tc_h->client_head,
774 if (cl->c_mq == tc_h->c_mq)
779 LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected.\n");
784 * Message was transmitted. Process the request.
786 * @param cls the client
787 * @param sma the send message that was sent
790 handle_send_message_ack (void *cls,
791 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
793 struct MyClient *client = cls;
794 GNUNET_SERVICE_client_continue (client->client);
800 * @brief Start the communicator part of the transport service
802 * @param communicator_available Callback to be called when a new communicator
804 * @param cfg Configuration
807 transport_communicator_start (
808 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
810 struct GNUNET_MQ_MessageHandler mh[] = {
811 GNUNET_MQ_hd_var_size (communicator_available,
812 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
813 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
815 GNUNET_MQ_hd_var_size (communicator_backchannel,
816 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
817 struct GNUNET_TRANSPORT_CommunicatorBackchannel,
819 GNUNET_MQ_hd_var_size (add_address,
820 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
821 struct GNUNET_TRANSPORT_AddAddressMessage,
823 // GNUNET_MQ_hd_fixed_size (del_address,
824 // GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
825 // struct GNUNET_TRANSPORT_DelAddressMessage,
827 GNUNET_MQ_hd_var_size (incoming_msg,
828 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
829 struct GNUNET_TRANSPORT_IncomingMessage,
831 GNUNET_MQ_hd_fixed_size (queue_create_ok,
832 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
833 struct GNUNET_TRANSPORT_CreateQueueResponse,
835 GNUNET_MQ_hd_fixed_size (queue_create_fail,
836 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
837 struct GNUNET_TRANSPORT_CreateQueueResponse,
839 GNUNET_MQ_hd_var_size (add_queue_message,
840 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
841 struct GNUNET_TRANSPORT_AddQueueMessage,
843 GNUNET_MQ_hd_fixed_size (update_queue_message,
844 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE,
845 struct GNUNET_TRANSPORT_UpdateQueueMessage,
847 // GNUNET_MQ_hd_fixed_size (del_queue_message,
848 // GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
849 // struct GNUNET_TRANSPORT_DelQueueMessage,
851 GNUNET_MQ_hd_fixed_size (send_message_ack,
852 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
853 struct GNUNET_TRANSPORT_SendMessageToAck,
855 GNUNET_MQ_handler_end ()
859 tc_h->sh = GNUNET_SERVICE_start ("transport",
865 GNUNET_assert (NULL != tc_h->sh);
870 * @brief Task run at shutdown to kill communicator and clean up
872 * @param cls Closure - Process of communicator
875 shutdown_process (struct GNUNET_OS_Process *proc)
877 if (0 != GNUNET_OS_process_kill (proc, SIGTERM))
879 LOG (GNUNET_ERROR_TYPE_WARNING,
880 "Error shutting down communicator with SIGERM, trying SIGKILL\n");
881 if (0 != GNUNET_OS_process_kill (proc, SIGKILL))
883 LOG (GNUNET_ERROR_TYPE_ERROR,
884 "Error shutting down communicator with SIGERM and SIGKILL\n");
887 GNUNET_OS_process_destroy (proc);
892 shutdown_communicator (void *cls)
894 struct GNUNET_OS_Process *proc = cls;
895 shutdown_process (proc);
900 * @brief Start the communicator
902 * @param cfgname Name of the communicator
906 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
907 const char *binary_name)
911 LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n");
912 binary = GNUNET_OS_get_libexec_binary_path (binary_name);
913 tc_h->c_proc = GNUNET_OS_start_process (GNUNET_YES,
914 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
923 if (NULL == tc_h->c_proc)
925 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!");
928 LOG (GNUNET_ERROR_TYPE_INFO, "started communicator\n");
929 GNUNET_free (binary);
934 * @brief Task run at shutdown to kill communicator and clean up
936 * @param cls Closure - Process of communicator
939 shutdown_nat (void *cls)
941 struct GNUNET_OS_Process *proc = cls;
942 shutdown_process (proc);
952 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
956 LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n");
957 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat");
958 tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_YES,
959 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
964 "gnunet-service-nat",
968 if (NULL == tc_h->nat_proc)
970 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start NAT!");
973 LOG (GNUNET_ERROR_TYPE_INFO, "started NAT\n");
974 GNUNET_free (binary);
979 * @brief Start communicator part of transport service and communicator
981 * @param service_name Name of the service
982 * @param cfg Configuration handle
983 * @param communicator_available_cb Callback that is called when a new
984 * @param add_address_cb Callback that is called when a new
985 * communicator becomes available
986 * @param cb_cls Closure to @a communicator_available_cb and @a
988 * @return Handle to the communicator duo
990 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
991 GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
992 const char *service_name,
993 const char *binary_name,
994 const char *cfg_filename,
995 const struct GNUNET_PeerIdentity *peer_id,
996 GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
997 communicator_available_cb,
998 GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb,
999 GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb,
1000 GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb,
1001 GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb,
1002 GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb,
1005 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
1007 LOG (GNUNET_ERROR_TYPE_DEBUG,
1008 "Starting new transport/communicator combo with config %s\n",
1011 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle);
1012 tc_h->cfg_filename = GNUNET_strdup (cfg_filename);
1013 tc_h->cfg = GNUNET_CONFIGURATION_create ();
1014 if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_load (tc_h->cfg, cfg_filename)))
1016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1017 _ ("Malformed configuration file `%s', exit ...\n"),
1019 GNUNET_free (tc_h->cfg_filename);
1020 GNUNET_CONFIGURATION_destroy (tc_h->cfg);
1024 tc_h->bc_enabled = GNUNET_CONFIGURATION_get_value_yesno (tc_h->cfg,
1025 "communicator-test",
1026 "BACKCHANNEL_ENABLED");
1027 tc_h->communicator_available_cb = communicator_available_cb;
1028 tc_h->add_address_cb = add_address_cb;
1029 tc_h->queue_create_reply_cb = queue_create_reply_cb;
1030 tc_h->add_queue_cb = add_queue_cb;
1031 tc_h->incoming_msg_cb = incoming_message_cb;
1032 tc_h->bc_cb = bc_cb;
1033 tc_h->peer_id = *peer_id;
1034 tc_h->cb_cls = cb_cls;
1036 /* Start communicator part of service */
1037 transport_communicator_start (tc_h);
1040 /* Schedule start communicator */
1041 communicator_start (tc_h,
1048 GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop (
1049 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
1051 shutdown_communicator (tc_h->c_proc);
1052 shutdown_service (tc_h->sh);
1053 shutdown_nat (tc_h->nat_proc);
1054 GNUNET_CONFIGURATION_destroy (tc_h->cfg);
1060 * @brief Instruct communicator to open a queue
1062 * @param tc_h Handle to communicator which shall open queue
1063 * @param peer_id Towards which peer
1064 * @param address For which address
1067 GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (
1068 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
1069 const struct GNUNET_PeerIdentity *peer_id,
1070 const char *address)
1072 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
1073 static uint32_t idgen;
1075 struct GNUNET_TRANSPORT_CreateQueue *msg;
1076 struct GNUNET_MQ_Envelope *env;
1080 GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
1081 tc_queue->tc_h = tc_h;
1082 prefix = GNUNET_HELLO_address_to_prefix (address);
1085 GNUNET_break (0); /* We got an invalid address!? */
1086 GNUNET_free (tc_queue);
1089 GNUNET_free (prefix);
1090 alen = strlen (address) + 1;
1092 GNUNET_MQ_msg_extra (msg, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
1093 msg->request_id = htonl (idgen++);
1094 tc_queue->qid = msg->request_id;
1095 msg->receiver = *peer_id;
1096 tc_queue->peer_id = *peer_id;
1097 memcpy (&msg[1], address, alen);
1098 if (NULL != tc_h->c_mq)
1100 GNUNET_MQ_send (tc_h->c_mq, env);
1104 tc_queue->open_queue_env = env;
1106 GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
1111 * @brief Instruct communicator to send data
1113 * @param tc_queue The queue to use for sending
1114 * @param cont function to call when done sending
1115 * @param cont_cls closure for @a cont
1116 * @param payload Data to send
1117 * @param payload_size Size of the @a payload
1120 GNUNET_TRANSPORT_TESTING_transport_communicator_send
1121 (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
1122 GNUNET_SCHEDULER_TaskCallback cont,
1124 const void *payload,
1125 size_t payload_size)
1127 struct GNUNET_MessageHeader *mh;
1128 struct GNUNET_TRANSPORT_SendMessageTo *msg;
1129 struct GNUNET_MQ_Envelope *env;
1131 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
1132 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_tmp;
1135 for (tc_queue_tmp = tc_h->queue_head;
1136 NULL != tc_queue_tmp;
1137 tc_queue_tmp = tc_queue_tmp->next)
1139 if (tc_queue_tmp->q_len <= 0)
1141 if (NULL == tc_queue)
1143 LOG (GNUNET_ERROR_TYPE_DEBUG,
1144 "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n",
1145 tc_queue_tmp->priority,
1146 tc_queue_tmp->q_len,
1148 tc_queue = tc_queue_tmp;
1151 if (tc_queue->priority < tc_queue_tmp->priority)
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n",
1155 tc_queue_tmp->priority,
1156 tc_queue_tmp->q_len,
1158 tc_queue = tc_queue_tmp;
1161 GNUNET_assert (NULL != tc_queue);
1162 if (tc_queue->q_len != GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED)
1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1165 "Sending message\n");
1166 inbox_size = sizeof (struct GNUNET_MessageHeader) + payload_size;
1167 env = GNUNET_MQ_msg_extra (msg,
1169 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
1170 GNUNET_assert (NULL != env);
1171 msg->qid = htonl (tc_queue->qid);
1172 msg->mid = tc_queue->mid++;
1173 msg->receiver = tc_queue->peer_id;
1174 mh = (struct GNUNET_MessageHeader *) &msg[1];
1175 mh->size = htons (inbox_size);
1176 mh->type = GNUNET_MESSAGE_TYPE_DUMMY;
1181 GNUNET_MQ_notify_sent (env,
1184 GNUNET_MQ_send (tc_queue->tc_h->c_mq,