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