2 This file is part of GNUnet.
3 Copyright (C) 2018 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_api2_communication.c
23 * @brief implementation of the gnunet_transport_communication_service.h API
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_transport_communication_service.h"
30 #include "gnunet_ats_transport_service.h"
31 #include "transport.h"
35 * How many messages do we keep at most in the queue to the
36 * transport service before we start to drop (default,
37 * can be changed via the configuration file).
39 #define DEFAULT_MAX_QUEUE_LENGTH 16
43 * Information we track per packet to enable flow control.
50 struct FlowControl *next;
55 struct FlowControl *prev;
58 * Function to call once the message was processed.
60 GNUNET_TRANSPORT_MessageCompletedCallback cb;
68 * Which peer is this about?
70 struct GNUNET_PeerIdentity sender;
73 * More-or-less unique ID for the message.
80 * Information we track per message to tell the transport about
81 * success or failures.
88 struct AckPending *next;
93 struct AckPending *prev;
96 * Communicator this entry belongs to.
98 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
101 * Which peer is this about?
103 struct GNUNET_PeerIdentity receiver;
106 * More-or-less unique ID for the message.
113 * Opaque handle to the transport service for communicators.
115 struct GNUNET_TRANSPORT_CommunicatorHandle
118 * Head of DLL of addresses this communicator offers to the transport service.
120 struct GNUNET_TRANSPORT_AddressIdentifier *ai_head;
123 * Tail of DLL of addresses this communicator offers to the transport service.
125 struct GNUNET_TRANSPORT_AddressIdentifier *ai_tail;
128 * DLL of messages awaiting flow control confirmation (ack).
130 struct FlowControl *fc_head;
133 * DLL of messages awaiting flow control confirmation (ack).
135 struct FlowControl *fc_tail;
138 * DLL of messages awaiting transmission confirmation (ack).
140 struct AckPending *ap_head;
143 * DLL of messages awaiting transmission confirmation (ack).
145 struct AckPending *ap_tail;
148 * DLL of queues we offer.
150 struct GNUNET_TRANSPORT_QueueHandle *queue_head;
153 * DLL of queues we offer.
155 struct GNUNET_TRANSPORT_QueueHandle *queue_tail;
160 const struct GNUNET_CONFIGURATION_Handle *cfg;
163 * Config section to use.
165 const char *config_section;
168 * Address prefix to use.
170 const char *addr_prefix;
173 * Function to call when the transport service wants us to initiate
174 * a communication channel with another peer.
176 GNUNET_TRANSPORT_CommunicatorMqInit mq_init;
179 * Closure for @e mq_init.
184 * Function to call when the transport service receives messages
185 * for a communicator (i.e. for NAT traversal or for non-bidirectional
188 GNUNET_TRANSPORT_CommunicatorNotify notify_cb;
191 * Closure for @e notify_Cb.
196 * Queue to talk to the transport service.
198 struct GNUNET_MQ_Handle *mq;
201 * Maximum permissable queue length.
203 unsigned long long max_queue_length;
206 * Flow-control identifier generator.
211 * Internal UUID for the address used in communication with the
217 * Queue identifier generator.
222 * Characteristics of the communicator.
224 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
230 * Handle returned to identify the internal data structure the transport
231 * API has created to manage a message queue to a particular peer.
233 struct GNUNET_TRANSPORT_QueueHandle
239 struct GNUNET_TRANSPORT_QueueHandle *next;
244 struct GNUNET_TRANSPORT_QueueHandle *prev;
247 * Handle this queue belongs to.
249 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
252 * Address used by the communication queue.
259 struct GNUNET_MQ_Handle *mq;
262 * Which peer we can communciate with.
264 struct GNUNET_PeerIdentity peer;
267 * Network type of the communciation queue.
269 enum GNUNET_NetworkType nt;
272 * Communication status of the queue.
274 enum GNUNET_TRANSPORT_ConnectionStatus cs;
277 * ID for this queue when talking to the transport service.
282 * Maximum transmission unit for the queue.
290 * Internal representation of an address a communicator is
291 * currently providing for the transport service.
293 struct GNUNET_TRANSPORT_AddressIdentifier
299 struct GNUNET_TRANSPORT_AddressIdentifier *next;
304 struct GNUNET_TRANSPORT_AddressIdentifier *prev;
307 * Transport handle where the address was added.
309 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
312 * The actual address.
317 * When does the address expire? (Expected lifetime of the
320 struct GNUNET_TIME_Relative expiration;
323 * Internal UUID for the address used in communication with the
329 * Network type for the address.
331 enum GNUNET_NetworkType nt;
337 * (re)connect our communicator to the transport service
339 * @param ch handle to reconnect
342 reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch);
346 * Send message to the transport service about address @a ai
347 * being now available.
349 * @param ai address to add
352 send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
354 struct GNUNET_MQ_Envelope *env;
355 struct GNUNET_TRANSPORT_AddAddressMessage *aam;
357 if (NULL == ai->ch->mq)
359 env = GNUNET_MQ_msg_extra (aam,
360 strlen (ai->address) + 1,
361 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS);
362 aam->expiration = GNUNET_TIME_relative_hton (ai->expiration);
363 aam->nt = htonl ((uint32_t) ai->nt);
366 strlen (ai->address) + 1);
367 GNUNET_MQ_send (ai->ch->mq,
373 * Send message to the transport service about address @a ai
374 * being no longer available.
376 * @param ai address to delete
379 send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
381 struct GNUNET_MQ_Envelope *env;
382 struct GNUNET_TRANSPORT_DelAddressMessage *dam;
384 if (NULL == ai->ch->mq)
386 env = GNUNET_MQ_msg (dam,
387 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS);
388 dam->aid = htonl (ai->aid);
389 GNUNET_MQ_send (ai->ch->mq,
395 * Send message to the transport service about queue @a qh
396 * being now available.
398 * @param qh queue to add
401 send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
403 struct GNUNET_MQ_Envelope *env;
404 struct GNUNET_TRANSPORT_AddQueueMessage *aqm;
406 if (NULL == qh->ch->mq)
408 env = GNUNET_MQ_msg_extra (aqm,
409 strlen (qh->address) + 1,
410 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP);
411 aqm->qid = htonl (qh->queue_id);
412 aqm->receiver = qh->peer;
413 aqm->nt = htonl ((uint32_t) qh->nt);
414 aqm->mtu = htonl (qh->mtu);
415 aqm->cs = htonl ((uint32_t) qh->cs);
418 strlen (qh->address) + 1);
419 GNUNET_MQ_send (qh->ch->mq,
425 * Send message to the transport service about queue @a qh
426 * being no longer available.
428 * @param qh queue to delete
431 send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
433 struct GNUNET_MQ_Envelope *env;
434 struct GNUNET_TRANSPORT_DelQueueMessage *dqm;
436 if (NULL == qh->ch->mq)
438 env = GNUNET_MQ_msg (dqm,
439 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN);
440 dqm->qid = htonl (qh->queue_id);
441 dqm->receiver = qh->peer;
442 GNUNET_MQ_send (qh->ch->mq,
448 * Disconnect from the transport service. Purges
449 * all flow control entries as we will no longer receive
450 * the ACKs. Purges the ack pending entries as the
451 * transport will no longer expect the confirmations.
453 * @param ch service to disconnect from
456 disconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
458 struct FlowControl *fcn;
459 struct AckPending *apn;
461 for (struct FlowControl *fc = ch->fc_head;
466 GNUNET_CONTAINER_DLL_remove (ch->fc_head,
473 for (struct AckPending *ap = ch->ap_head;
478 GNUNET_CONTAINER_DLL_remove (ch->ap_head,
485 GNUNET_MQ_destroy (ch->mq);
491 * Function called on MQ errors.
494 error_handler (void *cls,
495 enum GNUNET_MQ_Error error)
497 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
499 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
500 "MQ failure %d, reconnecting to transport service.\n",
503 /* TODO: maybe do this with exponential backoff/delay */
509 * Transport service acknowledged a message we gave it
510 * (with flow control enabled). Tell the communicator.
512 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
513 * @param incoming_ack the ack
516 handle_incoming_ack (void *cls,
517 const struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack)
519 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
521 for (struct FlowControl *fc = ch->fc_head;
525 if ( (fc->id == incoming_ack->fc_id) &&
526 (0 == memcmp (&fc->sender,
527 &incoming_ack->sender,
528 sizeof (struct GNUNET_PeerIdentity))) )
530 GNUNET_CONTAINER_DLL_remove (ch->fc_head,
541 /* TODO: maybe do this with exponential backoff/delay */
547 * Transport service wants us to create a queue. Check if @a cq
550 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
551 * @param cq the queue creation request
552 * @return #GNUNET_OK if @a smt is well-formed
555 check_create_queue (void *cls,
556 const struct GNUNET_TRANSPORT_CreateQueue *cq)
558 uint16_t len = ntohs (cq->header.size) - sizeof (*cq);
559 const char *addr = (const char *) &cq[1];
563 ('\0' != addr[len-1]) )
566 return GNUNET_SYSERR;
573 * Transport service wants us to create a queue. Tell the communicator.
575 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
576 * @param cq the queue creation request
579 handle_create_queue (void *cls,
580 const struct GNUNET_TRANSPORT_CreateQueue *cq)
582 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
583 const char *addr = (const char *) &cq[1];
584 struct GNUNET_TRANSPORT_CreateQueueResponse *cqr;
585 struct GNUNET_MQ_Envelope *env;
588 ch->mq_init (ch->mq_init_cls,
592 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
593 "Address `%s' invalid for this communicator\n",
595 env = GNUNET_MQ_msg (cqr,
596 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL);
600 env = GNUNET_MQ_msg (cqr,
601 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK);
603 cqr->request_id = cq->request_id;
604 GNUNET_MQ_send (ch->mq,
610 * Transport service wants us to send a message. Check if @a smt
613 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
614 * @param smt the transmission request
615 * @return #GNUNET_OK if @a smt is well-formed
618 check_send_msg (void *cls,
619 const struct GNUNET_TRANSPORT_SendMessageTo *smt)
621 uint16_t len = ntohs (smt->header.size) - sizeof (*smt);
622 const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1];
625 if (ntohs (mh->size) != len)
628 return GNUNET_SYSERR;
635 * Notify transport service about @a status of a message with
636 * @a mid sent to @a receiver.
639 * @param status #GNUNET_OK on success, #GNUNET_SYSERR on failure
640 * @param receiver which peer was the receiver
641 * @param mid message that the ack is about
644 send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
646 const struct GNUNET_PeerIdentity *receiver,
649 struct GNUNET_MQ_Envelope *env;
650 struct GNUNET_TRANSPORT_SendMessageToAck *ack;
652 env = GNUNET_MQ_msg (ack,
653 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK);
654 ack->status = htonl (status);
656 ack->receiver = *receiver;
657 GNUNET_MQ_send (ch->mq,
663 * Message queue transmission by communicator was successful,
664 * notify transport service.
666 * @param cls an `struct AckPending *`
669 send_ack_cb (void *cls)
671 struct AckPending *ap = cls;
672 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ap->ch;
674 GNUNET_CONTAINER_DLL_remove (ch->ap_head,
686 * Transport service wants us to send a message. Tell the communicator.
688 * @param cls our `struct GNUNET_TRANSPORT_CommunicatorHandle *`
689 * @param smt the transmission request
692 handle_send_msg (void *cls,
693 const struct GNUNET_TRANSPORT_SendMessageTo *smt)
695 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls;
696 const struct GNUNET_MessageHeader *mh;
697 struct GNUNET_MQ_Envelope *env;
698 struct AckPending *ap;
699 struct GNUNET_TRANSPORT_QueueHandle *qh;
701 for (qh = ch->queue_head;NULL != qh; qh = qh->next)
702 if ( (qh->queue_id == smt->qid) &&
703 (0 == memcmp (&qh->peer,
705 sizeof (struct GNUNET_PeerIdentity))) )
709 /* queue is already gone, tell transport this one failed */
710 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
711 "Transmission failed, queue no longer exists.\n");
718 ap = GNUNET_new (struct AckPending);
720 ap->receiver = smt->receiver;
722 GNUNET_CONTAINER_DLL_insert (ch->ap_head,
725 mh = (const struct GNUNET_MessageHeader *) &smt[1];
726 env = GNUNET_MQ_msg_copy (mh);
727 GNUNET_MQ_notify_sent (env,
730 GNUNET_MQ_send (qh->mq,
736 * (re)connect our communicator to the transport service
738 * @param ch handle to reconnect
741 reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
743 struct GNUNET_MQ_MessageHandler handlers[] = {
744 GNUNET_MQ_hd_fixed_size (incoming_ack,
745 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK,
746 struct GNUNET_TRANSPORT_IncomingMessageAck,
748 GNUNET_MQ_hd_var_size (create_queue,
749 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE,
750 struct GNUNET_TRANSPORT_CreateQueue,
752 GNUNET_MQ_hd_var_size (send_msg,
753 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG,
754 struct GNUNET_TRANSPORT_SendMessageTo,
756 // FIXME: handle backchannel notifications!
757 GNUNET_MQ_handler_end()
759 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam;
760 struct GNUNET_MQ_Envelope *env;
762 ch->mq = GNUNET_CLIENT_connect (ch->cfg,
769 env = GNUNET_MQ_msg_extra (cam,
770 strlen (ch->addr_prefix) + 1,
771 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR);
772 cam->cc = htonl ((uint32_t) ch->cc);
775 strlen (ch->addr_prefix) + 1);
776 GNUNET_MQ_send (ch->mq,
778 for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head;
781 send_add_address (ai);
782 for (struct GNUNET_TRANSPORT_QueueHandle *qh = ch->queue_head;
790 * Connect to the transport service.
792 * @param cfg configuration to use
793 * @param config_section section of the configuration to use for options
794 * @param addr_prefix address prefix for addresses supported by this
795 * communicator, could be NULL for incoming-only communicators
796 * @param cc what characteristics does the communicator have?
797 * @param mtu maximum message size supported by communicator, 0 if
798 * sending is not supported, SIZE_MAX for no MTU
799 * @param mq_init function to call to initialize a message queue given
800 * the address of another peer, can be NULL if the
801 * communicator only supports receiving messages
802 * @param mq_init_cls closure for @a mq_init
803 * @param notify_cb function to pass backchannel messages to communicator
804 * @param notify_cb_cls closure for @a notify_cb
805 * @return NULL on error
807 struct GNUNET_TRANSPORT_CommunicatorHandle *
808 GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
809 const char *config_section,
810 const char *addr_prefix,
811 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
812 GNUNET_TRANSPORT_CommunicatorMqInit mq_init,
814 GNUNET_TRANSPORT_CommunicatorNotify notify_cb,
817 struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
819 ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle);
821 ch->config_section = config_section;
822 ch->addr_prefix = addr_prefix;
823 ch->mq_init = mq_init;
824 ch->mq_init_cls = mq_init_cls;
825 ch->notify_cb = notify_cb;
826 ch->notify_cb_cls = notify_cb_cls;
830 GNUNET_CONFIGURATION_get_value_number (cfg,
833 &ch->max_queue_length))
834 ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
845 * Disconnect from the transport service.
847 * @param ch handle returned from connect
850 GNUNET_TRANSPORT_communicator_disconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
853 while (NULL != ch->ai_head)
855 GNUNET_break (0); /* communicator forgot to remove address, warn! */
856 GNUNET_TRANSPORT_communicator_address_remove (ch->ai_head);
862 /* ************************* Receiving *************************** */
866 * Notify transport service that the communicator has received
869 * @param ch connection to transport service
870 * @param sender presumed sender of the message (details to be checked
872 * @param msg the message
873 * @param cb function to call once handling the message is done, NULL if
874 * flow control is not supported by this communicator
875 * @param cb_cls closure for @a cb
876 * @return #GNUNET_OK if all is well, #GNUNET_NO if the message was
877 * immediately dropped due to memory limitations (communicator
878 * should try to apply back pressure),
879 * #GNUNET_SYSERR if the message could not be delivered because
880 * the tranport service is not yet up
883 GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
884 const struct GNUNET_PeerIdentity *sender,
885 const struct GNUNET_MessageHeader *msg,
886 GNUNET_TRANSPORT_MessageCompletedCallback cb,
889 struct GNUNET_MQ_Envelope *env;
890 struct GNUNET_TRANSPORT_IncomingMessage *im;
894 return GNUNET_SYSERR;
896 (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) )
898 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
899 "Dropping message: transprot is too slow, queue length %llu exceeded\n",
900 ch->max_queue_length);
904 msize = ntohs (msg->size);
905 env = GNUNET_MQ_msg_extra (im,
907 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG);
911 return GNUNET_SYSERR;
913 im->sender = *sender;
919 struct FlowControl *fc;
921 im->fc_on = htonl (GNUNET_YES);
922 im->fc_id = ch->fc_gen++;
923 fc = GNUNET_new (struct FlowControl);
924 fc->sender = *sender;
928 GNUNET_CONTAINER_DLL_insert (ch->fc_head,
932 GNUNET_MQ_send (ch->mq,
938 /* ************************* Discovery *************************** */
942 * Notify transport service that an MQ became available due to an
943 * "inbound" connection or because the communicator discovered the
944 * presence of another peer.
946 * @param ch connection to transport service
947 * @param peer peer with which we can now communicate
948 * @param address address in human-readable format, 0-terminated, UTF-8
949 * @param mtu maximum message size supported by queue, 0 if
950 * sending is not supported, SIZE_MAX for no MTU
951 * @param nt which network type does the @a address belong to?
952 * @param cc what characteristics does the communicator have?
953 * @param cs what is the connection status of the queue?
954 * @param mq message queue of the @a peer
955 * @return API handle identifying the new MQ
957 struct GNUNET_TRANSPORT_QueueHandle *
958 GNUNET_TRANSPORT_communicator_mq_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
959 const struct GNUNET_PeerIdentity *peer,
962 enum GNUNET_NetworkType nt,
963 enum GNUNET_TRANSPORT_ConnectionStatus cs,
964 struct GNUNET_MQ_Handle *mq)
966 struct GNUNET_TRANSPORT_QueueHandle *qh;
968 qh = GNUNET_new (struct GNUNET_TRANSPORT_QueueHandle);
971 qh->address = GNUNET_strdup (address);
976 qh->queue_id = ch->queue_gen++;
977 GNUNET_CONTAINER_DLL_insert (ch->queue_head,
986 * Notify transport service that an MQ became unavailable due to a
987 * disconnect or timeout.
989 * @param qh handle for the queue that must be invalidated
992 GNUNET_TRANSPORT_communicator_mq_del (struct GNUNET_TRANSPORT_QueueHandle *qh)
994 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = qh->ch;
997 GNUNET_CONTAINER_DLL_remove (ch->queue_head,
1000 GNUNET_MQ_destroy (qh->mq);
1001 GNUNET_free (qh->address);
1007 * Notify transport service about an address that this communicator
1008 * provides for this peer.
1010 * @param ch connection to transport service
1011 * @param address our address in human-readable format, 0-terminated, UTF-8
1012 * @param nt which network type does the address belong to?
1013 * @param expiration when does the communicator forsee this address expiring?
1015 struct GNUNET_TRANSPORT_AddressIdentifier *
1016 GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
1017 const char *address,
1018 enum GNUNET_NetworkType nt,
1019 struct GNUNET_TIME_Relative expiration)
1021 struct GNUNET_TRANSPORT_AddressIdentifier *ai;
1023 ai = GNUNET_new (struct GNUNET_TRANSPORT_AddressIdentifier);
1025 ai->address = GNUNET_strdup (address);
1027 ai->expiration = expiration;
1028 ai->aid = ch->aid_gen++;
1029 GNUNET_CONTAINER_DLL_insert (ch->ai_head,
1032 send_add_address (ai);
1038 * Notify transport service about an address that this communicator no
1039 * longer provides for this peer.
1041 * @param ai address that is no longer provided
1044 GNUNET_TRANSPORT_communicator_address_remove (struct GNUNET_TRANSPORT_AddressIdentifier *ai)
1046 struct GNUNET_TRANSPORT_CommunicatorHandle *ch = ai->ch;
1048 send_del_address (ai);
1049 GNUNET_CONTAINER_DLL_remove (ch->ai_head,
1052 GNUNET_free (ai->address);
1057 /* ************************* Backchannel *************************** */
1061 * The communicator asks the transport service to route a message via
1062 * a different path to another communicator service at another peer.
1063 * This must only be done for special control traffic (as there is no
1064 * flow control for this API), such as acknowledgements, and generally
1065 * only be done if the communicator is uni-directional (i.e. cannot
1066 * send the message back itself).
1068 * @param ch handle of this communicator
1069 * @param pid peer to send the message to
1070 * @param comm name of the communicator to send the message to
1071 * @param header header of the message to transmit and pass via the
1072 * notify-API to @a pid's communicator @a comm
1075 GNUNET_TRANSPORT_communicator_notify (struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
1076 const struct GNUNET_PeerIdentity *pid,
1078 const struct GNUNET_MessageHeader *header)
1080 struct GNUNET_MQ_Envelope *env;
1081 struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb;
1082 size_t slen = strlen (comm) + 1;
1083 uint16_t mlen = ntohs (header->size);
1085 GNUNET_assert (mlen + slen + sizeof (*cb) < UINT16_MAX);
1086 env = GNUNET_MQ_msg_extra (cb,
1088 GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL);
1093 memcpy (((char *)&cb[1]) + mlen,
1096 GNUNET_MQ_send (ch->mq,
1101 /* end of transport_api2_communication.c */