use NULL value in load_path_suffix to NOT load any files
[oweals/gnunet.git] / src / transport / transport-testing2.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2019 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
21 /**
22  * @file transport/transport-testing2.c
23  * @brief functions related to testing-tng
24  * @author Christian Grothoff
25  * @author Julius Bünger
26  */
27 #include "platform.h"
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"
36
37
38 #define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing2", __VA_ARGS__)
39
40
41 /**
42  * @brief Handle to a transport communicator
43  */
44 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
45 {
46   /**
47    * @brief Handle to the configuration
48    */
49   struct GNUNET_CONFIGURATION_Handle *cfg;
50
51   /**
52    * @brief File name of configuration file
53    */
54   char *cfg_filename;
55
56   /**
57    * @brief Handle to the transport service
58    */
59   struct GNUNET_SERVICE_Handle *tsh;
60
61   /**
62    * @brief Task that will be run on shutdown to stop and clean transport
63    * service
64    */
65   struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
66
67   /**
68    * @brief Handle to the client
69    */
70   struct GNUNET_SERVICE_Client *client;
71
72   /**
73    * @brief Handle to the client
74    */
75   struct GNUNET_MQ_Handle *c_mq;
76
77   /**
78    * @brief Process of the communicator
79    */
80   struct GNUNET_OS_Process *c_proc;
81
82   /**
83    * NAT process
84    */
85   struct GNUNET_OS_Process *nat_proc;
86
87   /**
88    * @brief Task that will be run on shutdown to stop and clean communicator
89    */
90   struct GNUNET_SCHEDULER_Task *c_shutdown_task;
91
92   /**
93    * @brief Characteristics of the communicator
94    */
95   enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
96
97   /**
98    * @brief Specifies supported addresses
99    */
100   char *c_addr_prefix;
101
102   /**
103    * @brief Specifies supported addresses
104    */
105   char *c_address;
106
107   /**
108    * @brief Head of the DLL of queues associated with this communicator
109    */
110   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
111
112   /**
113    * @brief Tail of the DLL of queues associated with this communicator
114    */
115   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
116
117   /* Callbacks + Closures */
118   /**
119    * @brief Callback called when a new communicator connects
120    */
121   GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
122     communicator_available_cb;
123
124   /**
125    * @brief Callback called when a new communicator connects
126    */
127   GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
128
129   /**
130    * @brief Callback called when a new communicator connects
131    */
132   GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
133
134   /**
135    * @brief Callback called when a new communicator connects
136    */
137   GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
138
139   /**
140    * @brief Callback called when a new communicator connects
141    */
142   GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb;
143
144   /**
145    * @brief Backchannel callback
146    */
147   GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb;
148
149   /**
150    * Our service handle
151    */
152   struct GNUNET_SERVICE_Handle *sh;
153
154   /**
155    * @brief Closure to the callback
156    */
157   void *cb_cls;
158
159   /**
160    * Backchannel supported
161    */
162   int bc_enabled;
163 };
164
165
166 /**
167  * @brief Queue of a communicator and some context
168  */
169 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue
170 {
171   /**
172    * @brief Handle to the TransportCommunicator
173    */
174   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
175
176   /**
177    * @brief Envelope to a message that requests the opening of the queue.
178    *
179    * If the client already requests queue(s), but the communicator is not yet
180    * connected, we cannot send the request to open the queue. Save it until the
181    * communicator becomes available and send it then.
182    */
183   struct GNUNET_MQ_Envelope *open_queue_env;
184
185   /**
186    * @brief Peer ID of the peer on the other side of the queue
187    */
188   struct GNUNET_PeerIdentity peer_id;
189
190   /**
191    * @brief Queue ID
192    */
193   uint32_t qid;
194
195   /**
196    * @brief Current message id
197    */
198   uint64_t mid;
199
200   /**
201    * An `enum GNUNET_NetworkType` in NBO.
202    */
203   uint32_t nt;
204
205   /**
206    * Maximum transmission unit, in NBO.  UINT32_MAX for unlimited.
207    */
208   uint32_t mtu;
209
210   /**
211    * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO.
212    */
213   uint32_t cs;
214
215   /**
216    * @brief Next element inside a DLL
217    */
218   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next;
219
220   /**
221    * @brief Previous element inside a DLL
222    */
223   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev;
224 };
225
226
227 /**
228  * @brief Handle/Context to a single transmission
229  */
230 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission
231 {
232 };
233
234
235 /**
236  * @brief Check whether incoming msg indicating available communicator is
237  * correct
238  *
239  * @param cls Closure
240  * @param msg Message struct
241  *
242  * @return GNUNET_YES in case message is correct
243  */
244 static int
245 check_communicator_available (
246   void *cls,
247   const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
248 {
249   uint16_t size;
250
251   size = ntohs (msg->header.size) - sizeof(*msg);
252   if (0 == size)
253     return GNUNET_OK; /* receive-only communicator */
254   GNUNET_MQ_check_zero_termination (msg);
255   return GNUNET_OK;
256 }
257
258
259 /**
260  * @brief Handle new communicator
261  *
262  * Store characteristics of communicator, call respective client callback.
263  *
264  * @param cls Closure - communicator handle
265  * @param msg Message struct
266  */
267 static void
268 handle_communicator_available (
269   void *cls,
270   const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg)
271 {
272   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
273   uint16_t size;
274
275   size = ntohs (msg->header.size) - sizeof(*msg);
276   if (0 == size)
277     return; /* receive-only communicator */
278   tc_h->c_characteristics = ntohl (msg->cc);
279   tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]);
280   if (NULL != tc_h->communicator_available_cb)
281   {
282     LOG (GNUNET_ERROR_TYPE_DEBUG, "calling communicator_available_cb()\n");
283     tc_h->communicator_available_cb (tc_h->cb_cls,
284                                      tc_h,
285                                      tc_h->c_characteristics,
286                                      tc_h->c_addr_prefix);
287   }
288   GNUNET_SERVICE_client_continue (tc_h->client);
289 }
290
291
292 /**
293  * Incoming message.  Test message is well-formed.
294  *
295  * @param cls the client
296  * @param msg the send message that was sent
297  * @return #GNUNET_OK if message is well-formed
298  */
299 static int
300 check_communicator_backchannel (void *cls,
301                                 const struct
302                                 GNUNET_TRANSPORT_CommunicatorBackchannel *msg)
303 {
304   // struct TransportClient *tc = cls;
305
306   // if (CT_COMMUNICATOR != tc->type)
307   // {
308   //  GNUNET_break (0);
309   //  return GNUNET_SYSERR;
310   // }
311   // GNUNET_MQ_check_boxed_message (msg);
312   return GNUNET_OK;
313 }
314
315
316 /**
317  * @brief Receive an incoming message.
318  *
319  * Pass the message to the client.
320  *
321  * @param cls Closure - communicator handle
322  * @param msg Message
323  */
324 static void
325 handle_communicator_backchannel (void *cls,
326                                  const struct
327                                  GNUNET_TRANSPORT_CommunicatorBackchannel *
328                                  bc_msg)
329 {
330   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
331   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *other_tc_h;
332   struct GNUNET_MessageHeader *msg;
333   msg = (struct GNUNET_MessageHeader *) &bc_msg[1];
334   uint16_t isize = ntohs (msg->size);
335   const char *target_communicator = ((const char *) msg) + isize;
336   struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
337   struct GNUNET_MQ_Envelope *env;
338
339
340   if (tc_h->bc_enabled != GNUNET_YES)
341   {
342     GNUNET_SERVICE_client_continue (tc_h->client);
343     return;
344   }
345   /* Find client providing this communicator */
346   /* Finally, deliver backchannel message to communicator */
347   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
348               "Delivering backchannel message of type %u to %s\n",
349               ntohs (msg->type),
350               target_communicator);
351   other_tc_h = tc_h->bc_cb (tc_h, msg, (struct
352                                         GNUNET_PeerIdentity*) &bc_msg->pid);
353   env = GNUNET_MQ_msg_extra (
354     cbi,
355     isize,
356     GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
357   cbi->pid = bc_msg->pid;
358   memcpy (&cbi[1], msg, isize);
359
360
361   GNUNET_MQ_send (other_tc_h->c_mq, env);
362   GNUNET_SERVICE_client_continue (tc_h->client);
363 }
364
365
366 /**
367  * Address of our peer added.  Test message is well-formed.
368  *
369  * @param cls the client
370  * @param aam the send message that was sent
371  * @return #GNUNET_OK if message is well-formed
372  */
373 static int
374 check_add_address (void *cls,
375                    const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
376 {
377   // if (CT_COMMUNICATOR != tc->type)
378   // {
379   //  GNUNET_break (0);
380   //  return GNUNET_SYSERR;
381   // }
382   GNUNET_MQ_check_zero_termination (msg);
383   return GNUNET_OK;
384 }
385
386
387 /**
388  * @brief The communicator informs about an address.
389  *
390  * Store address and call client callback.
391  *
392  * @param cls Closure - communicator handle
393  * @param msg Message
394  */
395 static void
396 handle_add_address (void *cls,
397                     const struct GNUNET_TRANSPORT_AddAddressMessage *msg)
398 {
399   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
400   uint16_t size;
401   size = ntohs (msg->header.size) - sizeof(*msg);
402   if (0 == size)
403     return; /* receive-only communicator */
404   LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size);
405   tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]);
406   if (NULL != tc_h->add_address_cb)
407   {
408     LOG (GNUNET_ERROR_TYPE_DEBUG, "calling add_address_cb()\n");
409     tc_h->add_address_cb (tc_h->cb_cls,
410                           tc_h,
411                           tc_h->c_address,
412                           GNUNET_TIME_relative_ntoh (msg->expiration),
413                           msg->aid,
414                           ntohl (msg->nt));
415   }
416   GNUNET_SERVICE_client_continue (tc_h->client);
417 }
418
419
420 /**
421  * Incoming message.  Test message is well-formed.
422  *
423  * @param cls the client
424  * @param msg the send message that was sent
425  * @return #GNUNET_OK if message is well-formed
426  */
427 static int
428 check_incoming_msg (void *cls,
429                     const struct GNUNET_TRANSPORT_IncomingMessage *msg)
430 {
431   // struct TransportClient *tc = cls;
432
433   // if (CT_COMMUNICATOR != tc->type)
434   // {
435   //  GNUNET_break (0);
436   //  return GNUNET_SYSERR;
437   // }
438   GNUNET_MQ_check_boxed_message (msg);
439   return GNUNET_OK;
440 }
441
442
443 /**
444  * @brief Receive an incoming message.
445  *
446  * Pass the message to the client.
447  *
448  * @param cls Closure - communicator handle
449  * @param msg Message
450  */
451 static void
452 handle_incoming_msg (void *cls,
453                      const struct GNUNET_TRANSPORT_IncomingMessage *inc_msg)
454 {
455   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
456   struct GNUNET_MessageHeader *msg;
457   msg = (struct GNUNET_MessageHeader *) &inc_msg[1];
458   size_t payload_len = ntohs (msg->size) - sizeof (struct
459                                                    GNUNET_MessageHeader);
460   LOG (GNUNET_ERROR_TYPE_DEBUG,
461        "Incoming message from communicator!\n");
462
463   if (NULL != tc_h->incoming_msg_cb)
464   {
465     tc_h->incoming_msg_cb (tc_h->cb_cls,
466                            tc_h,
467                            (char*) &msg[1],
468                            payload_len);
469   }
470   else
471   {
472     LOG (GNUNET_ERROR_TYPE_WARNING,
473          "Incoming message from communicator but no handler!\n");
474   }
475   if (GNUNET_YES == ntohl (inc_msg->fc_on))
476   {
477     /* send ACK when done to communicator for flow control! */
478     struct GNUNET_MQ_Envelope *env;
479     struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
480
481     env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK);
482     ack->reserved = htonl (0);
483     ack->fc_id = inc_msg->fc_id;
484     ack->sender = inc_msg->sender;
485     GNUNET_MQ_send (tc_h->c_mq, env);
486   }
487
488   GNUNET_SERVICE_client_continue (tc_h->client);
489 }
490
491
492 /**
493  * @brief Communicator informs that it tries to establish requested queue
494  *
495  * @param cls Closure - communicator handle
496  * @param msg Message
497  */
498 static void
499 handle_queue_create_ok (void *cls,
500                         const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
501 {
502   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
503
504   if (NULL != tc_h->queue_create_reply_cb)
505   {
506     tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_YES);
507   }
508   GNUNET_SERVICE_client_continue (tc_h->client);
509 }
510
511
512 /**
513  * @brief Communicator informs that it wont try establishing requested queue.
514  *
515  * It will not do so probably because the address is bougus (see comment to
516  * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL)
517  *
518  * @param cls Closure - communicator handle
519  * @param msg Message
520  */
521 static void
522 handle_queue_create_fail (
523   void *cls,
524   const struct GNUNET_TRANSPORT_CreateQueueResponse *msg)
525 {
526   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
527
528   if (NULL != tc_h->queue_create_reply_cb)
529   {
530     tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_NO);
531   }
532   GNUNET_SERVICE_client_continue (tc_h->client);
533 }
534
535
536 /**
537  * New queue became available.  Check message.
538  *
539  * @param cls the client
540  * @param aqm the send message that was sent
541  */
542 static int
543 check_add_queue_message (void *cls,
544                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
545 {
546   GNUNET_MQ_check_zero_termination (aqm);
547   return GNUNET_OK;
548 }
549
550
551 /**
552  * @brief Handle new queue
553  *
554  * Store context and call client callback.
555  *
556  * @param cls Closure - communicator handle
557  * @param msg Message struct
558  */
559 static void
560 handle_add_queue_message (void *cls,
561                           const struct GNUNET_TRANSPORT_AddQueueMessage *msg)
562 {
563   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
564   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
565
566   tc_queue = tc_h->queue_head;
567   if (NULL != tc_queue)
568   {
569     while (tc_queue->qid != msg->qid)
570     {
571       tc_queue = tc_queue->next;
572     }
573   }
574   else
575   {
576     tc_queue =
577       GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
578     tc_queue->tc_h = tc_h;
579     tc_queue->qid = msg->qid;
580     tc_queue->peer_id = msg->receiver;
581     GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
582   }
583   GNUNET_assert (tc_queue->qid == msg->qid);
584   GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver));
585   tc_queue->nt = msg->nt;
586   tc_queue->mtu = msg->mtu;
587   tc_queue->cs = msg->cs;
588   if (NULL != tc_h->add_queue_cb)
589   {
590     tc_h->add_queue_cb (tc_h->cb_cls, tc_h, tc_queue);
591   }
592   GNUNET_SERVICE_client_continue (tc_h->client);
593 }
594
595
596 /**
597  * @brief Shut down the service
598  *
599  * @param cls Closure - Handle to the service
600  */
601 static void
602 shutdown_service (void *cls)
603 {
604   struct GNUNET_SERVICE_Handle *h = cls;
605
606   GNUNET_SERVICE_stop (h);
607 }
608
609
610 /**
611  * @brief Callback called when new Client (Communicator) connects
612  *
613  * @param cls Closure - TransporCommmunicator Handle
614  * @param client Client
615  * @param mq Messagequeue
616  *
617  * @return TransportCommunicator Handle
618  */
619 static void *
620 connect_cb (void *cls,
621             struct GNUNET_SERVICE_Client *client,
622             struct GNUNET_MQ_Handle *mq)
623 {
624   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
625
626   LOG (GNUNET_ERROR_TYPE_DEBUG, "Client connected.\n");
627   tc_h->client = client;
628   tc_h->c_mq = mq;
629
630   if (NULL == tc_h->queue_head)
631     return tc_h;
632   /* Iterate over queues. They are yet to be opened. Request opening. */
633   for (struct
634        GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter =
635          tc_h->queue_head;
636        NULL != tc_queue_iter;
637        tc_queue_iter = tc_queue_iter->next)
638   {
639     if (NULL == tc_queue_iter->open_queue_env)
640       continue;
641     /* Send the previously created mq envelope to request the creation of the
642      * queue. */
643     GNUNET_MQ_send (tc_h->c_mq,
644                     tc_queue_iter->open_queue_env);
645     tc_queue_iter->open_queue_env = NULL;
646   }
647   return tc_h;
648 }
649
650
651 /**
652  * @brief Callback called when Client disconnects
653  *
654  * @param cls Closure - TransportCommunicator Handle
655  * @param client Client
656  * @param internal_cls TransporCommmunicator Handle
657  */
658 static void
659 disconnect_cb (void *cls,
660                struct GNUNET_SERVICE_Client *client,
661                void *internal_cls)
662 {
663   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
664
665   LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected.\n");
666   tc_h->client = NULL;
667 }
668
669
670 /**
671  * Message was transmitted.  Process the request.
672  *
673  * @param cls the client
674  * @param sma the send message that was sent
675  */
676 static void
677 handle_send_message_ack (void *cls,
678                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
679 {
680   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
681   GNUNET_SERVICE_client_continue (tc_h->client);
682   // NOP
683 }
684
685
686 /**
687  * @brief Start the communicator part of the transport service
688  *
689  * @param communicator_available Callback to be called when a new communicator
690  * becomes available
691  * @param cfg Configuration
692  */
693 static void
694 transport_communicator_start (
695   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
696 {
697   struct GNUNET_MQ_MessageHandler mh[] = {
698     GNUNET_MQ_hd_var_size (communicator_available,
699                            GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
700                            struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
701                            tc_h),
702     GNUNET_MQ_hd_var_size (communicator_backchannel,
703                            GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
704                            struct GNUNET_TRANSPORT_CommunicatorBackchannel,
705                            tc_h),
706     GNUNET_MQ_hd_var_size (add_address,
707                            GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
708                            struct GNUNET_TRANSPORT_AddAddressMessage,
709                            tc_h),
710     // GNUNET_MQ_hd_fixed_size (del_address,
711     //                         GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
712     //                         struct GNUNET_TRANSPORT_DelAddressMessage,
713     //                         NULL),
714     GNUNET_MQ_hd_var_size (incoming_msg,
715                            GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
716                            struct GNUNET_TRANSPORT_IncomingMessage,
717                            tc_h),
718     GNUNET_MQ_hd_fixed_size (queue_create_ok,
719                              GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
720                              struct GNUNET_TRANSPORT_CreateQueueResponse,
721                              tc_h),
722     GNUNET_MQ_hd_fixed_size (queue_create_fail,
723                              GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
724                              struct GNUNET_TRANSPORT_CreateQueueResponse,
725                              tc_h),
726     GNUNET_MQ_hd_var_size (add_queue_message,
727                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
728                            struct GNUNET_TRANSPORT_AddQueueMessage,
729                            tc_h),
730     // GNUNET_MQ_hd_fixed_size (del_queue_message,
731     //                         GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
732     //                         struct GNUNET_TRANSPORT_DelQueueMessage,
733     //                         NULL),
734     GNUNET_MQ_hd_fixed_size (send_message_ack,
735                              GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
736                              struct GNUNET_TRANSPORT_SendMessageToAck,
737                              tc_h),
738     GNUNET_MQ_handler_end ()
739   };
740
741
742   tc_h->sh = GNUNET_SERVICE_start ("transport",
743                                    tc_h->cfg,
744                                    &connect_cb,
745                                    &disconnect_cb,
746                                    tc_h,
747                                    mh);
748   GNUNET_assert (NULL != tc_h->sh);
749 }
750
751
752 /**
753  * @brief Task run at shutdown to kill communicator and clean up
754  *
755  * @param cls Closure - Process of communicator
756  */
757 static void
758 shutdown_process (struct GNUNET_OS_Process *proc)
759 {
760   if (0 != GNUNET_OS_process_kill (proc, SIGTERM))
761   {
762     LOG (GNUNET_ERROR_TYPE_WARNING,
763          "Error shutting down communicator with SIGERM, trying SIGKILL\n");
764     if (0 != GNUNET_OS_process_kill (proc, SIGKILL))
765     {
766       LOG (GNUNET_ERROR_TYPE_ERROR,
767            "Error shutting down communicator with SIGERM and SIGKILL\n");
768     }
769   }
770   GNUNET_OS_process_destroy (proc);
771 }
772
773
774 static void
775 shutdown_communicator (void *cls)
776 {
777   struct GNUNET_OS_Process *proc = cls;
778   shutdown_process (proc);
779 }
780
781
782 /**
783  * @brief Start the communicator
784  *
785  * @param cfgname Name of the communicator
786  */
787 static void
788 communicator_start (
789   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
790   const char *binary_name)
791 {
792   char *binary;
793
794   LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n");
795   binary = GNUNET_OS_get_libexec_binary_path (binary_name);
796   tc_h->c_proc = GNUNET_OS_start_process (GNUNET_YES,
797                                           GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
798                                           NULL,
799                                           NULL,
800                                           NULL,
801                                           binary,
802                                           binary_name,
803                                           "-c",
804                                           tc_h->cfg_filename,
805                                           NULL);
806   if (NULL == tc_h->c_proc)
807   {
808     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!");
809     return;
810   }
811   LOG (GNUNET_ERROR_TYPE_INFO, "started communicator\n");
812   GNUNET_free (binary);
813 }
814
815
816 /**
817  * @brief Task run at shutdown to kill communicator and clean up
818  *
819  * @param cls Closure - Process of communicator
820  */
821 static void
822 shutdown_nat (void *cls)
823 {
824   struct GNUNET_OS_Process *proc = cls;
825   shutdown_process (proc);
826 }
827
828
829 /**
830  * @brief Start NAT
831  *
832  */
833 static void
834 nat_start (
835   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
836 {
837   char *binary;
838
839   LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n");
840   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat");
841   tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_YES,
842                                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
843                                             NULL,
844                                             NULL,
845                                             NULL,
846                                             binary,
847                                             "gnunet-service-nat",
848                                             "-c",
849                                             tc_h->cfg_filename,
850                                             NULL);
851   if (NULL == tc_h->nat_proc)
852   {
853     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start NAT!");
854     return;
855   }
856   LOG (GNUNET_ERROR_TYPE_INFO, "started NAT\n");
857   GNUNET_free (binary);
858 }
859
860
861 static void
862 do_shutdown (void *cls)
863 {
864   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls;
865   shutdown_communicator (tc_h->c_proc);
866   shutdown_service (tc_h->sh);
867   shutdown_nat (tc_h->nat_proc);
868 }
869
870
871 /**
872  * @brief Start communicator part of transport service and communicator
873  *
874  * @param service_name Name of the service
875  * @param cfg Configuration handle
876  * @param communicator_available_cb Callback that is called when a new
877  * @param add_address_cb Callback that is called when a new
878  * communicator becomes available
879  * @param cb_cls Closure to @a communicator_available_cb and @a
880  *
881  * @return Handle to the communicator duo
882  */
883 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *
884 GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
885   const char *service_name,
886   const char *binary_name,
887   const char *cfg_filename,
888   GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
889   communicator_available_cb,
890   GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb,
891   GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb,
892   GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb,
893   GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb,
894   GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb,
895   void *cb_cls)
896 {
897   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h;
898
899   tc_h =
900     GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle);
901   tc_h->cfg_filename = GNUNET_strdup (cfg_filename);
902   tc_h->cfg = GNUNET_CONFIGURATION_create ();
903   if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_load (tc_h->cfg, cfg_filename)))
904   {
905     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
906                 _ ("Malformed configuration file `%s', exit ...\n"),
907                 cfg_filename);
908     GNUNET_free (tc_h->cfg_filename);
909     GNUNET_CONFIGURATION_destroy (tc_h->cfg);
910     GNUNET_free (tc_h);
911     return NULL;
912   }
913   tc_h->bc_enabled = GNUNET_CONFIGURATION_get_value_yesno (tc_h->cfg,
914                                                            "communicator-test",
915                                                            "BACKCHANNEL_ENABLED");
916   tc_h->communicator_available_cb = communicator_available_cb;
917   tc_h->add_address_cb = add_address_cb;
918   tc_h->queue_create_reply_cb = queue_create_reply_cb;
919   tc_h->add_queue_cb = add_queue_cb;
920   tc_h->incoming_msg_cb = incoming_message_cb;
921   tc_h->bc_cb = bc_cb;
922   tc_h->cb_cls = cb_cls;
923
924   /* Start communicator part of service */
925   transport_communicator_start (tc_h);
926   /* Start NAT */
927   nat_start (tc_h);
928   /* Schedule start communicator */
929   communicator_start (tc_h,
930                       binary_name);
931   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, tc_h);
932   return tc_h;
933 }
934
935
936 /**
937  * @brief Instruct communicator to open a queue
938  *
939  * @param tc_h Handle to communicator which shall open queue
940  * @param peer_id Towards which peer
941  * @param address For which address
942  */
943 void
944 GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (
945   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h,
946   const struct GNUNET_PeerIdentity *peer_id,
947   const char *address)
948 {
949   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
950   static uint32_t idgen;
951   char *prefix;
952   struct GNUNET_TRANSPORT_CreateQueue *msg;
953   struct GNUNET_MQ_Envelope *env;
954   size_t alen;
955
956   tc_queue =
957     GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue);
958   tc_queue->tc_h = tc_h;
959   prefix = GNUNET_HELLO_address_to_prefix (address);
960   if (NULL == prefix)
961   {
962     GNUNET_break (0);  /* We got an invalid address!? */
963     GNUNET_free (tc_queue);
964     return;
965   }
966   GNUNET_free (prefix);
967   alen = strlen (address) + 1;
968   env =
969     GNUNET_MQ_msg_extra (msg, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
970   msg->request_id = htonl (idgen++);
971   tc_queue->qid = msg->request_id;
972   msg->receiver = *peer_id;
973   tc_queue->peer_id = *peer_id;
974   memcpy (&msg[1], address, alen);
975   if (NULL != tc_h->c_mq)
976   {
977     GNUNET_MQ_send (tc_h->c_mq, env);
978   }
979   else
980   {
981     tc_queue->open_queue_env = env;
982   }
983   GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue);
984 }
985
986
987 /**
988  * @brief Instruct communicator to send data
989  *
990  * @param tc_queue The queue to use for sending
991  * @param payload Data to send
992  * @param payload_size Size of the payload
993  *
994  * @return Handle to the transmission
995  */
996 struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission *
997 GNUNET_TRANSPORT_TESTING_transport_communicator_send
998   (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue,
999   const void *payload,
1000   size_t payload_size)
1001 {
1002   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission *tc_t;
1003   struct GNUNET_MessageHeader *mh;
1004   struct GNUNET_TRANSPORT_SendMessageTo *msg;
1005   struct GNUNET_MQ_Envelope *env;
1006   size_t inbox_size;
1007
1008   inbox_size = sizeof(struct GNUNET_MessageHeader) + payload_size;
1009   mh = GNUNET_malloc (inbox_size);
1010   mh->size = htons (inbox_size);
1011   mh->type = GNUNET_MESSAGE_TYPE_DUMMY;
1012   memcpy (&mh[1],
1013           payload,
1014           payload_size);
1015   env = GNUNET_MQ_msg_extra (msg,
1016                              inbox_size,
1017                              GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
1018   msg->qid = htonl (tc_queue->qid);
1019   msg->mid = tc_queue->mid++;
1020   msg->receiver = tc_queue->peer_id;
1021   memcpy (&msg[1], mh, inbox_size);
1022   GNUNET_free (mh);
1023   GNUNET_MQ_send (tc_queue->tc_h->c_mq, env);
1024   // GNUNET_assert (0); // FIXME: not iplemented!
1025   return tc_t;
1026 }