2 This file is part of GNUnet
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/plugin_transport_udp.c
23 * @brief Implementation of the UDP NAT punching
25 * @author Christian Grothoff
26 * @author Nathan Evans
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_fragmentation_lib.h"
32 #include "gnunet_nat_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_resolver_service.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_constants.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_transport_service.h"
39 #include "gnunet_transport_plugin.h"
40 #include "transport.h"
42 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
45 #define DEBUG_UDP GNUNET_EXTRA_LOGGING
48 * MTU for fragmentation subsystem. Should be conservative since
49 * all communicating peers MUST work with this MTU.
54 * Number of messages we can defragment in parallel. We only really
55 * defragment 1 message at a time, but if messages get re-ordered, we
56 * may want to keep knowledge about the previous message to avoid
57 * discarding the current message in favor of a single fragment of a
58 * previous message. 3 should be good since we don't expect massive
59 * message reorderings with UDP.
61 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
64 * We keep a defragmentation queue per sender address. How many
65 * sender addresses do we support at the same time? Memory consumption
66 * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this
67 * value. (So 128 corresponds to 12 MB and should suffice for
68 * connecting to roughly 128 peers via UDP).
70 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
74 * UDP Message-Packet header (after defragmentation).
81 struct GNUNET_MessageHeader header;
84 * Always zero for now.
89 * What is the identity of the sender
91 struct GNUNET_PeerIdentity sender;
97 * UDP ACK Message-Packet header (after defragmentation).
99 struct UDP_ACK_Message
104 struct GNUNET_MessageHeader header;
107 * Desired delay for flow control
112 * What is the identity of the sender
114 struct GNUNET_PeerIdentity sender;
119 * Network format for IPv4 addresses.
121 struct IPv4UdpAddress
124 * IPv4 address, in network byte order.
126 uint32_t ipv4_addr GNUNET_PACKED;
129 * Port number, in network byte order.
131 uint16_t u4_port GNUNET_PACKED;
136 * Network format for IPv6 addresses.
138 struct IPv6UdpAddress
144 struct in6_addr ipv6_addr GNUNET_PACKED;
147 * Port number, in network byte order.
149 uint16_t u6_port GNUNET_PACKED;
153 /* Forward definition */
158 * Session with another peer. FIXME: why not make this into
159 * a regular 'struct Session' and pass it around!?
165 * Which peer is this session for?
167 struct GNUNET_PeerIdentity target;
170 * Pointer to the global plugin struct.
172 struct Plugin *plugin;
175 * Address of the other peer
177 const struct sockaddr *sock_addr;
182 * Function to call upon completion of the transmission.
184 GNUNET_TRANSPORT_TransmitContinuation cont;
187 * Closure for 'cont'.
192 * Current outgoing message to this peer.
194 struct GNUNET_FRAGMENT_Context *frag;
196 struct GNUNET_TIME_Absolute valid_until;
198 GNUNET_SCHEDULER_TaskIdentifier invalidation_task;
200 GNUNET_SCHEDULER_TaskIdentifier delayed_cont_task;
203 * Desired delay for next sending we send to other peer
205 struct GNUNET_TIME_Relative flow_delay_for_other_peer;
208 * Desired delay for next sending we received from other peer
210 struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
215 * Data structure to track defragmentation contexts based
216 * on the source of the UDP traffic.
218 struct ReceiveContext
222 * Defragmentation context.
224 struct GNUNET_DEFRAGMENT_Context *defrag;
227 * Source address this receive context is for (allocated at the
228 * end of the struct).
230 const struct sockaddr *src_addr;
233 * Reference to master plugin struct.
235 struct Plugin *plugin;
238 * Node in the defrag heap.
240 struct GNUNET_CONTAINER_HeapNode *hnode;
243 * Length of 'src_addr'
247 struct GNUNET_PeerIdentity id;
253 * Encapsulation of all of the state of the plugin.
261 struct GNUNET_TRANSPORT_PluginEnvironment *env;
264 * Session of peers with whom we are currently connected,
265 * map of peer identity to 'struct PeerSession'.
267 struct GNUNET_CONTAINER_MultiHashMap *sessions;
270 * Session of peers with whom we are currently connected,
271 * map of peer identity to 'struct PeerSession'.
273 struct GNUNET_CONTAINER_MultiHashMap *inbound_sessions;
276 * Heap with all of our defragmentation activities.
278 struct GNUNET_CONTAINER_Heap *defrags;
283 GNUNET_SCHEDULER_TaskIdentifier select_task;
286 * Tokenizer for inbound messages.
288 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
291 * Bandwidth tracker to limit global UDP traffic.
293 struct GNUNET_BANDWIDTH_Tracker tracker;
296 * Address we were told to bind to exclusively (IPv4).
301 * Address we were told to bind to exclusively (IPv6).
306 * Handle to NAT traversal support.
308 struct GNUNET_NAT_Handle *nat;
313 struct GNUNET_NETWORK_FDSet *rs;
316 * The read socket for IPv4
318 struct GNUNET_NETWORK_Handle *sockv4;
321 * The read socket for IPv6
323 struct GNUNET_NETWORK_Handle *sockv6;
331 * The read socket for IPv4
333 struct GNUNET_NETWORK_Handle *sockv4_broadcast;
336 * ID of select broadcast task
338 GNUNET_SCHEDULER_TaskIdentifier select_broadcast_task;
341 * ID of select broadcast task
343 GNUNET_SCHEDULER_TaskIdentifier send_broadcast_task;
348 struct GNUNET_NETWORK_FDSet *broadcast_rs;
353 struct GNUNET_TIME_Relative broadcast_interval;
356 * expected delay for ACKs
358 struct GNUNET_TIME_Relative last_expected_delay;
361 * Port we broadcasting on.
363 uint16_t broadcast_port;
371 * Port we advertise on.
377 struct PeerSessionIteratorContext
379 struct Session * result;
386 * Lookup the session for the given peer.
388 * @param plugin the plugin
389 * @param peer peer's identity
390 * @return NULL if we have no session
392 static struct Session *
393 find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
395 return GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
401 inbound_session_iterator (void *cls,
402 const GNUNET_HashCode * key,
405 struct PeerSessionIteratorContext *psc = cls;
406 struct Session *s = value;
407 if (s->addrlen == psc->addrlen)
409 if (0 == memcmp (&s[1], psc->addr, s->addrlen))
412 if (psc->result != NULL)
419 * Lookup the session for the given peer.
421 * @param plugin the plugin
422 * @param peer peer's identity
423 * @return NULL if we have no session
425 static struct Session *
426 find_inbound_session (struct Plugin *plugin,
427 const struct GNUNET_PeerIdentity *peer,
428 const void * addr, size_t addrlen)
430 struct PeerSessionIteratorContext psc;
432 psc.addrlen = addrlen;
435 GNUNET_CONTAINER_multihashmap_get_multiple(plugin->inbound_sessions, &peer->hashPubKey, &inbound_session_iterator, &psc);
441 inbound_session_by_addr_iterator (void *cls,
442 const GNUNET_HashCode * key,
445 struct PeerSessionIteratorContext *psc = cls;
446 struct Session *s = value;
447 if (s->addrlen == psc->addrlen)
449 if (0 == memcmp (&s[1], psc->addr, s->addrlen))
452 if (psc->result != NULL)
459 * Lookup the session for the given peer just by address.
461 * @param plugin the plugin
462 * @param addr address
463 * @param addrlen address length
464 * @return NULL if we have no session
466 static struct Session *
467 find_inbound_session_by_addr (struct Plugin *plugin, const void * addr, size_t addrlen)
469 struct PeerSessionIteratorContext psc;
471 psc.addrlen = addrlen;
474 GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions, &inbound_session_by_addr_iterator, &psc);
480 * Destroy a session, plugin is being unloaded.
483 * @param key hash of public key of target peer
484 * @param value a 'struct PeerSession*' to clean up
485 * @return GNUNET_OK (continue to iterate)
488 destroy_session (void *cls, const GNUNET_HashCode * key, void *value)
490 struct Session *peer_session = value;
492 if (peer_session->frag != NULL)
493 GNUNET_FRAGMENT_context_destroy (peer_session->frag);
494 if (GNUNET_SCHEDULER_NO_TASK != peer_session->delayed_cont_task)
495 GNUNET_SCHEDULER_cancel (peer_session->delayed_cont_task);
496 GNUNET_free (peer_session);
501 * Destroy a session, plugin is being unloaded.
504 * @param key hash of public key of target peer
505 * @param value a 'struct PeerSession*' to clean up
506 * @return GNUNET_OK (continue to iterate)
509 destroy_inbound_session (void *cls, const GNUNET_HashCode * key, void *value)
511 struct Session *s = value;
513 if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
514 GNUNET_SCHEDULER_cancel(s->invalidation_task);
515 if (GNUNET_SCHEDULER_NO_TASK != s->delayed_cont_task)
516 GNUNET_SCHEDULER_cancel (s->delayed_cont_task);
522 * Disconnect from a remote node. Clean up session if we have one for this peer
524 * @param cls closure for this call (should be handle to Plugin)
525 * @param target the peeridentity of the peer to disconnect
526 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
529 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
531 struct Plugin *plugin = cls;
532 struct Session *session;
534 session = find_session (plugin, target);
537 GNUNET_assert (GNUNET_OK ==
538 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
542 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->inbound_sessions,
544 &destroy_inbound_session, NULL);
545 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
546 LOG (GNUNET_ERROR_TYPE_ERROR,
549 plugin->last_expected_delay = GNUNET_FRAGMENT_context_destroy (session->frag);
550 if (GNUNET_SCHEDULER_NO_TASK != session->delayed_cont_task)
551 GNUNET_SCHEDULER_cancel (session->delayed_cont_task);
552 if (session->cont != NULL)
553 session->cont (session->cont_cls, target, GNUNET_SYSERR);
554 GNUNET_free (session);
559 * Actually send out the message.
561 * @param plugin the plugin
562 * @param sa the address to send the message to
563 * @param msg message to transmit
564 * @return the number of bytes written
567 udp_send (struct Plugin *plugin, const struct sockaddr *sa,
568 const struct GNUNET_MessageHeader *msg)
573 switch (sa->sa_family)
576 if (NULL == plugin->sockv4)
579 GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, ntohs (msg->size),
580 sa, slen = sizeof (struct sockaddr_in));
583 if (NULL == plugin->sockv6)
586 GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, ntohs (msg->size),
587 sa, slen = sizeof (struct sockaddr_in6));
593 if (GNUNET_SYSERR == sent)
595 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
596 LOG (GNUNET_ERROR_TYPE_ERROR,
597 "UDP transmited %u-byte message to %s (%d: %s)\n",
598 (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen),
599 (int) sent, (sent < 0) ? STRERROR (errno) : "ok");
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "UDP transmited %u-byte message to %s (%d: %s)\n",
604 (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen),
605 (int) sent, (sent < 0) ? STRERROR (errno) : "ok");
611 * Function that is called with messages created by the fragmentation
612 * module. In the case of the 'proc' callback of the
613 * GNUNET_FRAGMENT_context_create function, this function must
614 * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
616 * @param cls closure, the 'struct PeerSession'
617 * @param msg the message that was created
620 send_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
622 struct Session *session = cls;
624 udp_send (session->plugin, session->sock_addr, msg);
625 GNUNET_FRAGMENT_context_transmission_done (session->frag);
629 static struct Session *
630 create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
631 const void *addr, size_t addrlen,
632 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
634 struct Session * peer_session;
635 const struct IPv4UdpAddress *t4;
636 const struct IPv6UdpAddress *t6;
637 struct sockaddr_in *v4;
638 struct sockaddr_in6 *v6;
643 case sizeof (struct IPv4UdpAddress):
644 if (NULL == plugin->sockv4)
650 GNUNET_malloc (sizeof (struct Session) +
651 sizeof (struct sockaddr_in));
652 len = sizeof (struct sockaddr_in);
653 v4 = (struct sockaddr_in *) &peer_session[1];
654 v4->sin_family = AF_INET;
655 #if HAVE_SOCKADDR_IN_SIN_LEN
656 v4->sin_len = sizeof (struct sockaddr_in);
658 v4->sin_port = t4->u4_port;
659 v4->sin_addr.s_addr = t4->ipv4_addr;
661 case sizeof (struct IPv6UdpAddress):
662 if (NULL == plugin->sockv6)
668 GNUNET_malloc (sizeof (struct Session) +
669 sizeof (struct sockaddr_in6));
670 len = sizeof (struct sockaddr_in6);
671 v6 = (struct sockaddr_in6 *) &peer_session[1];
672 v6->sin6_family = AF_INET6;
673 #if HAVE_SOCKADDR_IN_SIN_LEN
674 v6->sin6_len = sizeof (struct sockaddr_in6);
676 v6->sin6_port = t6->u6_port;
677 v6->sin6_addr = t6->ipv6_addr;
680 /* Must have a valid address to send to */
685 peer_session->valid_until = GNUNET_TIME_absolute_get_zero ();
686 peer_session->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
687 peer_session->addrlen = len;
688 peer_session->target = *target;
689 peer_session->plugin = plugin;
690 peer_session->sock_addr = (const struct sockaddr *) &peer_session[1];
691 peer_session->cont = cont;
692 peer_session->cont_cls = cont_cls;
698 udp_address_to_string (void *cls, const void *addr, size_t addrlen);
702 udp_call_continuation (void *cls,
703 const struct GNUNET_SCHEDULER_TaskContext *tc)
705 struct Session *s = cls;
706 GNUNET_TRANSPORT_TransmitContinuation cont = s->cont;
708 s->delayed_cont_task = GNUNET_SCHEDULER_NO_TASK;
710 cont (s->cont_cls, &s->target, GNUNET_OK);
715 * Function that can be used by the transport service to transmit
716 * a message using the plugin.
719 * @param target who should receive this message (ignored by UDP)
720 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
721 * @param msgbuf_size the size of the msgbuf to send
722 * @param priority how important is the message (ignored by UDP)
723 * @param timeout when should we time out (give up) if we can not transmit?
724 * @param session identifier used for this session (NULL for UDP)
725 * @param addr the addr to send the message to
726 * @param addrlen the len of addr
727 * @param force_address not used, we had better have an address to send to
728 * because we are stateless!!
729 * @param cont continuation to call once the message has
730 * been transmitted (or if the transport is ready
731 * for the next transmission call; or if the
732 * peer disconnected...)
733 * @param cont_cls closure for cont
735 * @return the number of bytes written (may return 0 and the message can
736 * still be transmitted later!)
739 udp_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
740 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
741 struct GNUNET_TIME_Relative timeout, struct Session *session,
742 const void *addr, size_t addrlen, int force_address,
743 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
745 struct Plugin *plugin = cls;
746 struct Session *peer_session;
748 const struct IPv4UdpAddress *t4;
749 const struct IPv6UdpAddress *t6;
750 size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
752 struct UDPMessage *udp;
753 struct GNUNET_TIME_Relative delta;
755 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
758 return GNUNET_SYSERR;
761 LOG (GNUNET_ERROR_TYPE_DEBUG,
762 "UDP transmits %u-byte message to `%s' using address `%s' session 0x%X mode %i\n",
763 msgbuf_size, GNUNET_i2s (target),
764 udp_address_to_string (NULL, addr, addrlen),
765 session, force_address);
767 if ((force_address == GNUNET_SYSERR) && (session == NULL))
768 return GNUNET_SYSERR;
771 /* safety check: comparing address to address stored in session */
772 if ((session != NULL) && (addr != NULL) && (addrlen != 0))
775 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value (
776 plugin->inbound_sessions, &target->hashPubKey, s));
778 if (0 != memcmp (&s->target, target, sizeof (struct GNUNET_PeerIdentity)))
779 return GNUNET_SYSERR;
782 case sizeof (struct IPv4UdpAddress):
783 if (NULL == plugin->sockv4)
786 cont (cont_cls, target, GNUNET_SYSERR);
787 return GNUNET_SYSERR;
790 if (s->addrlen != (sizeof (struct sockaddr_in)))
791 return GNUNET_SYSERR;
792 struct sockaddr_in *a4 = (struct sockaddr_in *) s->sock_addr;
793 GNUNET_assert (a4->sin_port == t4->u4_port);
794 GNUNET_assert (0 == memcmp(&a4->sin_addr, &t4->ipv4_addr, sizeof (struct in_addr)));
795 LOG (GNUNET_ERROR_TYPE_DEBUG,
796 "Session 0x%X successfully checked!\n", session);
798 case sizeof (struct IPv6UdpAddress):
799 if (NULL == plugin->sockv6)
802 cont (cont_cls, target, GNUNET_SYSERR);
803 return GNUNET_SYSERR;
806 GNUNET_assert (s->addrlen == sizeof (struct sockaddr_in6));
807 struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) s->sock_addr;
808 GNUNET_assert (a6->sin6_port == t6->u6_port);
809 GNUNET_assert (0 == memcmp(&a6->sin6_addr, &t6->ipv6_addr, sizeof (struct in6_addr)));
810 LOG (GNUNET_ERROR_TYPE_DEBUG,
811 "Session 0x%X successfully checked!\n", session);
814 /* Must have a valid address to send to */
819 if ((addr == NULL) || (addrlen == 0))
820 return GNUNET_SYSERR;
821 peer_session = create_session (plugin, target, addr, addrlen, cont, cont_cls);
822 if (peer_session == NULL)
825 cont (cont_cls, target, GNUNET_SYSERR);
826 return GNUNET_SYSERR;;
830 udp = (struct UDPMessage *) mbuf;
831 udp->header.size = htons (mlen);
832 udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
833 udp->reserved = htonl (0);
834 udp->sender = *plugin->env->my_identity;
835 memcpy (&udp[1], msgbuf, msgbuf_size);
838 delta = GNUNET_TIME_absolute_get_remaining (s->flow_delay_from_other_peer);
840 delta = GNUNET_TIME_UNIT_ZERO;
843 mlen = udp_send (plugin, peer_session->sock_addr, &udp->header);
846 if ( (delta.rel_value > 0) &&
850 s->cont_cls = cont_cls;
851 s->delayed_cont_task = GNUNET_SCHEDULER_add_delayed (delta,
852 &udp_call_continuation,
856 cont (cont_cls, target, (mlen > 0) ? GNUNET_OK : GNUNET_SYSERR);
858 GNUNET_free_non_null (peer_session);
862 GNUNET_assert (GNUNET_OK ==
863 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
866 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
868 GNUNET_FRAGMENT_context_create (plugin->env->stats, UDP_MTU,
870 plugin->last_expected_delay,
871 &udp->header, &send_fragment,
879 * Closure for 'process_inbound_tokenized_messages'
881 struct SourceInformation
886 struct GNUNET_PeerIdentity sender;
894 * Number of bytes in source address.
898 struct Session * session;
903 * Message tokenizer has broken up an incomming message. Pass it on
906 * @param cls the 'struct Plugin'
907 * @param client the 'struct SourceInformation'
908 * @param hdr the actual message
911 process_inbound_tokenized_messages (void *cls, void *client,
912 const struct GNUNET_MessageHeader *hdr)
914 struct Plugin *plugin = cls;
915 struct SourceInformation *si = client;
916 struct GNUNET_ATS_Information distance;
917 struct GNUNET_TIME_Relative delay;
920 distance.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
921 distance.value = htonl (1);
923 LOG (GNUNET_ERROR_TYPE_DEBUG,
924 "Giving Session %X %s to transport\n", si->session, GNUNET_i2s(&si->session->target));
925 delay = plugin->env->receive (plugin->env->cls, &si->sender, hdr, &distance, 1, si->session,
927 si->session->flow_delay_for_other_peer = delay;
931 invalidation_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
933 struct Session * s = cls;
934 s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
935 LOG (GNUNET_ERROR_TYPE_ERROR,
936 "Session %X (`%s') is now invalid\n", s, GNUNET_a2s (s->sock_addr,s->addrlen));
938 s->plugin->env->session_end(s->plugin->env->cls, &s->target, s);
939 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(s->plugin->inbound_sessions, &s->target.hashPubKey, s));
945 * We've received a UDP Message. Process it (pass contents to main service).
947 * @param plugin plugin context
948 * @param msg the message
949 * @param sender_addr sender address
950 * @param sender_addr_len number of bytes in sender_addr
953 process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
954 const struct sockaddr *sender_addr,
955 socklen_t sender_addr_len)
957 struct SourceInformation si;
958 struct IPv4UdpAddress u4;
959 struct IPv6UdpAddress u6;
963 if (0 != ntohl (msg->reserved))
968 if (ntohs (msg->header.size) <
969 sizeof (struct GNUNET_MessageHeader) + sizeof (struct UDPMessage))
975 /* convert address */
976 switch (sender_addr->sa_family)
979 GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in));
980 u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr;
981 u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port;
986 GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in6));
987 u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr;
988 u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port;
997 LOG (GNUNET_ERROR_TYPE_DEBUG,
998 "Received message with %u bytes from peer `%s' at `%s'\n",
999 (unsigned int) ntohs (msg->header.size),
1000 GNUNET_i2s (&msg->sender), GNUNET_a2s (sender_addr,
1004 /* create a session for inbound connections */
1005 const struct UDPMessage * udp_msg = (const struct UDPMessage *) msg;
1006 LOG (GNUNET_ERROR_TYPE_DEBUG,
1007 "Lookup inbound UDP sessions for peer `%s' address `%s'\n",
1008 GNUNET_i2s (&udp_msg->sender),
1009 udp_address_to_string(NULL, arg, args));
1011 struct Session * s = NULL;
1012 s = find_inbound_session (plugin, &udp_msg->sender, sender_addr, sender_addr_len);
1016 LOG (GNUNET_ERROR_TYPE_DEBUG,
1017 "Found existing inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
1019 GNUNET_i2s (&s->target),
1020 udp_address_to_string(NULL, arg, args));
1024 s = create_session (plugin, &udp_msg->sender, arg, args, NULL, NULL);
1025 LOG (GNUNET_ERROR_TYPE_DEBUG,
1026 "Creating inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
1028 GNUNET_i2s (&s->target),
1029 udp_address_to_string(NULL, arg, args));
1031 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (plugin->inbound_sessions,
1032 &s->target.hashPubKey,
1034 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1036 s->valid_until = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1037 if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
1039 GNUNET_SCHEDULER_cancel(s->invalidation_task);
1040 s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
1041 LOG (GNUNET_ERROR_TYPE_DEBUG,
1042 "Rescheduling %X' `%s'\n",
1043 s, udp_address_to_string(NULL, arg, args));
1045 s->invalidation_task = GNUNET_SCHEDULER_add_delayed(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &invalidation_task, s);
1046 /* iterate over all embedded messages */
1047 si.sender = msg->sender;
1051 GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
1052 ntohs (msg->header.size) -
1053 sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
1058 * Process a defragmented message.
1060 * @param cls the 'struct ReceiveContext'
1061 * @param msg the message
1064 fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1066 struct ReceiveContext *rc = cls;
1068 if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
1073 if (ntohs (msg->size) < sizeof (struct UDPMessage))
1078 process_udp_message (rc->plugin, (const struct UDPMessage *) msg,
1079 rc->src_addr, rc->addr_len);
1084 * Transmit an acknowledgement.
1086 * @param cls the 'struct ReceiveContext'
1087 * @param id message ID (unused)
1088 * @param msg ack to transmit
1091 ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
1093 struct ReceiveContext *rc = cls;
1095 size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size);
1097 struct UDP_ACK_Message *udp_ack;
1101 s = find_inbound_session_by_addr (rc->plugin, rc->src_addr, rc->addr_len);
1104 if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
1105 delay = s->flow_delay_for_other_peer.rel_value;
1112 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK to `%s' including delay of %u ms\n",
1113 GNUNET_a2s (rc->src_addr,
1114 (rc->src_addr->sa_family ==
1115 AF_INET) ? sizeof (struct sockaddr_in) :
1116 sizeof (struct sockaddr_in6)),
1119 udp_ack = (struct UDP_ACK_Message *) buf;
1120 udp_ack->header.size = htons ((uint16_t) msize);
1121 udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
1122 udp_ack->delay = htonl (delay);
1123 udp_ack->sender = *rc->plugin->env->my_identity;
1124 memcpy (&udp_ack[1], msg, ntohs (msg->size));
1125 (void) udp_send (rc->plugin, rc->src_addr, &udp_ack->header);
1130 * Closure for 'find_receive_context'.
1132 struct FindReceiveContext
1135 * Where to store the result.
1137 struct ReceiveContext *rc;
1142 const struct sockaddr *addr;
1145 * Number of bytes in 'addr'.
1149 struct Session * session;
1154 * Scan the heap for a receive context with the given address.
1156 * @param cls the 'struct FindReceiveContext'
1157 * @param node internal node of the heap
1158 * @param element value stored at the node (a 'struct ReceiveContext')
1159 * @param cost cost associated with the node
1160 * @return GNUNET_YES if we should continue to iterate,
1164 find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
1165 void *element, GNUNET_CONTAINER_HeapCostType cost)
1167 struct FindReceiveContext *frc = cls;
1168 struct ReceiveContext *e = element;
1170 if ((frc->addr_len == e->addr_len) &&
1171 (0 == memcmp (frc->addr, e->src_addr, frc->addr_len)))
1181 * Read and process a message from the given socket.
1183 * @param plugin the overall plugin
1184 * @param rsock socket to read from
1187 udp_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1193 const struct GNUNET_MessageHeader *msg;
1194 const struct GNUNET_MessageHeader *ack;
1195 struct Session *peer_session;
1196 const struct UDP_ACK_Message *udp_ack;
1197 struct ReceiveContext *rc;
1198 struct GNUNET_TIME_Absolute now;
1199 struct FindReceiveContext frc;
1200 struct Session * s = NULL;
1201 struct GNUNET_TIME_Relative flow_delay;
1203 fromlen = sizeof (addr);
1204 memset (&addr, 0, sizeof (addr));
1206 GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1207 (struct sockaddr *) &addr, &fromlen);
1208 if (ret < sizeof (struct GNUNET_MessageHeader))
1210 GNUNET_break_op (0);
1213 msg = (const struct GNUNET_MessageHeader *) buf;
1215 LOG (GNUNET_ERROR_TYPE_DEBUG,
1216 "UDP received %u-byte message from `%s' type %i\n", (unsigned int) ret,
1217 GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs(msg->type));
1219 if (ret != ntohs (msg->size))
1221 GNUNET_break_op (0);
1224 switch (ntohs (msg->type))
1226 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
1227 if (ntohs (msg->size) < sizeof (struct UDPMessage))
1229 GNUNET_break_op (0);
1232 process_udp_message (plugin, (const struct UDPMessage *) msg,
1233 (const struct sockaddr *) addr, fromlen);
1235 case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
1237 if (ntohs (msg->size) <
1238 sizeof (struct UDP_ACK_Message) + sizeof (struct GNUNET_MessageHeader))
1240 GNUNET_break_op (0);
1243 udp_ack = (const struct UDP_ACK_Message *) msg;
1244 s = find_inbound_session(plugin, &udp_ack->sender, addr, fromlen);
1247 flow_delay.rel_value = (uint64_t) ntohl(udp_ack->delay);
1249 LOG (GNUNET_ERROR_TYPE_DEBUG,
1250 "We received a sending delay of %llu\n", flow_delay.rel_value);
1252 s->flow_delay_from_other_peer = GNUNET_TIME_relative_to_absolute (flow_delay);
1254 ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
1255 if (ntohs (ack->size) != ntohs (msg->size) - sizeof (struct UDP_ACK_Message))
1257 GNUNET_break_op (0);
1261 LOG (GNUNET_ERROR_TYPE_DEBUG,
1262 "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
1263 (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1264 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1267 peer_session = find_session (plugin, &udp_ack->sender);
1268 if (NULL == peer_session)
1271 LOG (GNUNET_ERROR_TYPE_DEBUG,
1272 "Session for ACK not found, dropping ACK!\n");
1276 if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (peer_session->frag, ack))
1278 GNUNET_assert (GNUNET_OK ==
1279 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
1283 plugin->last_expected_delay =
1284 GNUNET_FRAGMENT_context_destroy (peer_session->frag);
1285 if (peer_session->cont != NULL)
1286 peer_session->cont (peer_session->cont_cls, &udp_ack->sender, GNUNET_OK);
1287 GNUNET_free (peer_session);
1289 case GNUNET_MESSAGE_TYPE_FRAGMENT:
1291 frc.addr = (const struct sockaddr *) addr;
1292 frc.addr_len = fromlen;
1293 GNUNET_CONTAINER_heap_iterate (plugin->defrags, &find_receive_context,
1295 now = GNUNET_TIME_absolute_get ();
1299 /* need to create a new RC */
1300 rc = GNUNET_malloc (sizeof (struct ReceiveContext) + fromlen);
1301 memcpy (&rc[1], addr, fromlen);
1302 rc->src_addr = (const struct sockaddr *) &rc[1];
1303 rc->addr_len = fromlen;
1304 rc->plugin = plugin;
1306 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1307 UDP_MAX_MESSAGES_IN_DEFRAG, rc,
1308 &fragment_msg_proc, &ack_proc);
1310 GNUNET_CONTAINER_heap_insert (plugin->defrags, rc,
1311 (GNUNET_CONTAINER_HeapCostType)
1315 LOG (GNUNET_ERROR_TYPE_DEBUG,
1316 "UDP processes %u-byte fragment from `%s'\n",
1317 (unsigned int) ntohs (msg->size),
1318 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1321 if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (rc->defrag, msg))
1323 /* keep this 'rc' from expiring */
1324 GNUNET_CONTAINER_heap_update_cost (plugin->defrags, rc->hnode,
1325 (GNUNET_CONTAINER_HeapCostType)
1328 if (GNUNET_CONTAINER_heap_get_size (plugin->defrags) >
1329 UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1331 /* remove 'rc' that was inactive the longest */
1332 rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags);
1333 GNUNET_assert (NULL != rc);
1334 GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1339 GNUNET_break_op (0);
1346 * We have been notified that our writeset has something to read. We don't
1347 * know which socket needs to be read, so we have to check each one
1348 * Then reschedule this function to be called again once more is available.
1350 * @param cls the plugin handle
1351 * @param tc the scheduling context (for rescheduling this function again)
1354 udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1356 struct Plugin *plugin = cls;
1358 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1359 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1361 if ((NULL != plugin->sockv4) &&
1362 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
1363 udp_read (plugin, plugin->sockv4);
1364 if ((NULL != plugin->sockv6) &&
1365 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
1366 udp_read (plugin, plugin->sockv6);
1367 plugin->select_task =
1368 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1369 GNUNET_SCHEDULER_NO_TASK,
1370 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1371 NULL, &udp_plugin_select, plugin);
1377 * Read and process a message from the given socket.
1379 * @param plugin the overall plugin
1380 * @param rsock socket to read from
1383 udp_broadcast_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1389 const struct GNUNET_MessageHeader *msg;
1391 fromlen = sizeof (addr);
1392 memset (&addr, 0, sizeof (addr));
1393 ret = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1394 (struct sockaddr *) &addr, &fromlen);
1395 if (ret < sizeof (struct GNUNET_MessageHeader))
1397 GNUNET_break_op (0);
1400 msg = (const struct GNUNET_MessageHeader *) buf;
1402 LOG (GNUNET_ERROR_TYPE_ERROR,
1403 "UDP received %u-byte message from `%s' type %i\n", (unsigned int) ret,
1404 GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs(msg->type));
1406 if (ret != ntohs (msg->size))
1408 GNUNET_break_op (0);
1415 udp_broadcast_send (void *cls,
1416 const struct GNUNET_SCHEDULER_TaskContext *tc)
1418 struct Plugin * plugin = cls;
1419 struct GNUNET_MessageHeader msg;
1422 plugin->send_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1424 struct sockaddr_in baddr;
1425 baddr.sin_family = AF_INET;
1426 baddr.sin_port = htons (plugin->broadcast_port);
1427 baddr.sin_addr.s_addr=htonl(-1); /* send message to 255.255.255.255 */
1429 msg.size = htons(sizeof (struct GNUNET_MessageHeader));
1430 msg.type = htons (500);
1432 sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4_broadcast, &msg, ntohs (msg.size),
1433 (const struct sockaddr *) &baddr, sizeof (struct sockaddr_in));
1435 LOG (GNUNET_ERROR_TYPE_ERROR,
1436 "Sent broadcast with %i bytes\n", sent);
1437 plugin->send_broadcast_task = GNUNET_SCHEDULER_add_delayed(plugin->broadcast_interval, &udp_broadcast_send, plugin);
1442 * We have been notified that our writeset has something to read. We don't
1443 * know which socket needs to be read, so we have to check each one
1444 * Then reschedule this function to be called again once more is available.
1446 * @param cls the plugin handle
1447 * @param tc the scheduling context (for rescheduling this function again)
1450 udp_plugin_broadcast_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1452 struct Plugin *plugin = cls;
1454 plugin->select_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1455 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1458 if ((NULL != plugin->sockv4_broadcast) &&
1459 (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4_broadcast)))
1460 udp_broadcast_read (plugin, plugin->sockv4_broadcast);
1462 plugin->select_broadcast_task =
1463 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1464 GNUNET_SCHEDULER_NO_TASK,
1465 GNUNET_TIME_UNIT_FOREVER_REL, plugin->broadcast_rs,
1466 NULL, &udp_plugin_broadcast_select, plugin);
1472 * Check if the given port is plausible (must be either our listen
1473 * port or our advertised port). If it is neither, we return
1476 * @param plugin global variables
1477 * @param in_port port number to check
1478 * @return GNUNET_OK if port is either open_port or adv_port
1481 check_port (struct Plugin *plugin, uint16_t in_port)
1483 if ((in_port == plugin->port) || (in_port == plugin->aport))
1485 return GNUNET_SYSERR;
1490 * Function that will be called to check if a binary address for this
1491 * plugin is well-formed and corresponds to an address for THIS peer
1492 * (as per our configuration). Naturally, if absolutely necessary,
1493 * plugins can be a bit conservative in their answer, but in general
1494 * plugins should make sure that the address does not redirect
1495 * traffic to a 3rd party that might try to man-in-the-middle our
1498 * @param cls closure, should be our handle to the Plugin
1499 * @param addr pointer to the address
1500 * @param addrlen length of addr
1501 * @return GNUNET_OK if this is a plausible address for this peer
1502 * and transport, GNUNET_SYSERR if not
1506 udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1508 struct Plugin *plugin = cls;
1509 struct IPv4UdpAddress *v4;
1510 struct IPv6UdpAddress *v6;
1512 if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
1513 (addrlen != sizeof (struct IPv6UdpAddress)))
1515 GNUNET_break_op (0);
1516 return GNUNET_SYSERR;
1518 if (addrlen == sizeof (struct IPv4UdpAddress))
1520 v4 = (struct IPv4UdpAddress *) addr;
1521 if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
1522 return GNUNET_SYSERR;
1524 GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
1525 sizeof (struct in_addr)))
1526 return GNUNET_SYSERR;
1530 v6 = (struct IPv6UdpAddress *) addr;
1531 if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1533 GNUNET_break_op (0);
1534 return GNUNET_SYSERR;
1536 if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
1537 return GNUNET_SYSERR;
1539 GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
1540 sizeof (struct in6_addr)))
1541 return GNUNET_SYSERR;
1548 * Function called for a quick conversion of the binary address to
1549 * a numeric address. Note that the caller must not free the
1550 * address and that the next call to this function is allowed
1551 * to override the address again.
1553 * @param cls closure
1554 * @param addr binary address
1555 * @param addrlen length of the address
1556 * @return string representing the same address
1559 udp_address_to_string (void *cls, const void *addr, size_t addrlen)
1561 static char rbuf[INET6_ADDRSTRLEN + 10];
1562 char buf[INET6_ADDRSTRLEN];
1566 const struct IPv4UdpAddress *t4;
1567 const struct IPv6UdpAddress *t6;
1571 if (addrlen == sizeof (struct IPv6UdpAddress))
1575 port = ntohs (t6->u6_port);
1576 memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1579 else if (addrlen == sizeof (struct IPv4UdpAddress))
1583 port = ntohs (t4->u4_port);
1584 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1589 GNUNET_break_op (0);
1592 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1593 GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
1600 * Closure for 'append_port'.
1602 struct PrettyPrinterContext
1605 * Function to call with the result.
1607 GNUNET_TRANSPORT_AddressStringCallback asc;
1610 * Clsoure for 'asc'.
1615 * Port to add after the IP address.
1622 * Append our port and forward the result.
1624 * @param cls a 'struct PrettyPrinterContext'
1625 * @param hostname result from DNS resolver
1628 append_port (void *cls, const char *hostname)
1630 struct PrettyPrinterContext *ppc = cls;
1633 if (hostname == NULL)
1635 ppc->asc (ppc->asc_cls, NULL);
1639 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1640 ppc->asc (ppc->asc_cls, ret);
1646 * Convert the transports address to a nice, human-readable
1649 * @param cls closure
1650 * @param type name of the transport that generated the address
1651 * @param addr one of the addresses of the host, NULL for the last address
1652 * the specific address format depends on the transport
1653 * @param addrlen length of the address
1654 * @param numeric should (IP) addresses be displayed in numeric form?
1655 * @param timeout after how long should we give up?
1656 * @param asc function to call on each string
1657 * @param asc_cls closure for asc
1660 udp_plugin_address_pretty_printer (void *cls, const char *type,
1661 const void *addr, size_t addrlen,
1663 struct GNUNET_TIME_Relative timeout,
1664 GNUNET_TRANSPORT_AddressStringCallback asc,
1667 struct PrettyPrinterContext *ppc;
1670 struct sockaddr_in a4;
1671 struct sockaddr_in6 a6;
1672 const struct IPv4UdpAddress *u4;
1673 const struct IPv6UdpAddress *u6;
1676 if (addrlen == sizeof (struct IPv6UdpAddress))
1679 memset (&a6, 0, sizeof (a6));
1680 a6.sin6_family = AF_INET6;
1681 #if HAVE_SOCKADDR_IN_SIN_LEN
1682 a6.sin6_len = sizeof (a6);
1684 a6.sin6_port = u6->u6_port;
1685 memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
1686 port = ntohs (u6->u6_port);
1690 else if (addrlen == sizeof (struct IPv4UdpAddress))
1693 memset (&a4, 0, sizeof (a4));
1694 a4.sin_family = AF_INET;
1695 #if HAVE_SOCKADDR_IN_SIN_LEN
1696 a4.sin_len = sizeof (a4);
1698 a4.sin_port = u4->u4_port;
1699 a4.sin_addr.s_addr = u4->ipv4_addr;
1700 port = ntohs (u4->u4_port);
1706 /* invalid address */
1707 GNUNET_break_op (0);
1708 asc (asc_cls, NULL);
1711 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1713 ppc->asc_cls = asc_cls;
1715 GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
1720 * Our external IP address/port mapping has changed.
1722 * @param cls closure, the 'struct LocalAddrList'
1723 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1724 * the previous (now invalid) one
1725 * @param addr either the previous or the new public IP address
1726 * @param addrlen actual lenght of the address
1729 udp_nat_port_map_callback (void *cls, int add_remove,
1730 const struct sockaddr *addr, socklen_t addrlen)
1732 struct Plugin *plugin = cls;
1733 struct IPv4UdpAddress u4;
1734 struct IPv6UdpAddress u6;
1738 /* convert 'addr' to our internal format */
1739 switch (addr->sa_family)
1742 GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1743 u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1744 u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
1749 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1750 memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
1751 sizeof (struct in6_addr));
1752 u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1760 /* modify our published address list */
1761 plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
1766 * The exported method. Makes the core api available via a global and
1767 * returns the udp transport API.
1769 * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1770 * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1773 libgnunet_plugin_transport_udp_init (void *cls)
1775 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1776 unsigned long long port;
1777 unsigned long long aport;
1778 unsigned long long bport;
1779 struct GNUNET_TRANSPORT_PluginFunctions *api;
1780 struct Plugin *plugin;
1781 int sockets_created;
1783 struct GNUNET_TIME_Relative interval;
1784 struct sockaddr_in serverAddrv4;
1785 struct sockaddr_in6 serverAddrv6;
1786 struct sockaddr *serverAddr;
1787 struct sockaddr *addrs[2];
1788 socklen_t addrlens[2];
1791 unsigned long long udp_max_bps;
1794 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
1798 broadcast = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp", "BROADCAST");
1799 if (broadcast == GNUNET_SYSERR)
1800 broadcast = GNUNET_NO;
1802 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp", "BROADCAST_INTERVAL", &interval))
1803 interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10);
1806 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "BROADCAST_PORT",
1811 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1812 "MAX_BPS", &udp_max_bps))
1813 udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */
1815 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1816 "ADVERTISED_PORT", &aport))
1820 LOG (GNUNET_ERROR_TYPE_WARNING,
1821 _("Given `%s' option is out of range: %llu > %u\n"), "PORT",
1825 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1826 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1828 plugin = GNUNET_malloc (sizeof (struct Plugin));
1829 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
1830 GNUNET_BANDWIDTH_value_init ((uint32_t)
1832 plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
1833 plugin->port = port;
1834 plugin->aport = aport;
1835 plugin->broadcast_port = bport;
1836 plugin->broadcast = broadcast;
1838 plugin->broadcast_interval = interval;
1839 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1842 api->send = &udp_plugin_send;
1843 api->disconnect = &udp_disconnect;
1844 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
1845 api->address_to_string = &udp_address_to_string;
1846 api->check_address = &udp_plugin_check_address;
1849 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1850 "BINDTO", &plugin->bind4_address))
1852 LOG (GNUNET_ERROR_TYPE_DEBUG,
1853 "Binding udp plugin to specific address: `%s'\n",
1854 plugin->bind4_address);
1855 if (1 != inet_pton (AF_INET, plugin->bind4_address, &serverAddrv4.sin_addr))
1857 GNUNET_free (plugin->bind4_address);
1858 GNUNET_free (plugin);
1865 GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1866 "BINDTO6", &plugin->bind6_address))
1868 LOG (GNUNET_ERROR_TYPE_DEBUG,
1869 "Binding udp plugin to specific address: `%s'\n",
1870 plugin->bind6_address);
1872 inet_pton (AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1874 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
1875 plugin->bind6_address);
1876 GNUNET_free_non_null (plugin->bind4_address);
1877 GNUNET_free (plugin->bind6_address);
1878 GNUNET_free (plugin);
1885 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1887 GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
1889 plugin->inbound_sessions =
1890 GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
1892 sockets_created = 0;
1894 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "nat",
1897 plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1898 if (NULL == plugin->sockv6)
1900 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1904 #if HAVE_SOCKADDR_IN_SIN_LEN
1905 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1907 serverAddrv6.sin6_family = AF_INET6;
1908 serverAddrv6.sin6_addr = in6addr_any;
1909 serverAddrv6.sin6_port = htons (plugin->port);
1910 addrlen = sizeof (serverAddrv6);
1911 serverAddr = (struct sockaddr *) &serverAddrv6;
1913 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
1914 ntohs (serverAddrv6.sin6_port));
1917 while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
1920 serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1922 LOG (GNUNET_ERROR_TYPE_DEBUG,
1923 "IPv6 Binding failed, trying new port %d\n",
1924 ntohs (serverAddrv6.sin6_port));
1929 GNUNET_NETWORK_socket_close (plugin->sockv6);
1930 plugin->sockv6 = NULL;
1934 if (plugin->sockv6 != NULL)
1936 addrs[sockets_created] = (struct sockaddr *) &serverAddrv6;
1937 addrlens[sockets_created] = sizeof (serverAddrv6);
1944 GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
1945 plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1946 if (NULL == plugin->sockv4)
1948 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1952 #if HAVE_SOCKADDR_IN_SIN_LEN
1953 serverAddrv4.sin_len = sizeof (serverAddrv4);
1955 serverAddrv4.sin_family = AF_INET;
1956 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1957 serverAddrv4.sin_port = htons (plugin->port);
1958 addrlen = sizeof (serverAddrv4);
1959 serverAddr = (struct sockaddr *) &serverAddrv4;
1961 LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
1962 ntohs (serverAddrv4.sin_port));
1965 while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
1968 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1970 LOG (GNUNET_ERROR_TYPE_DEBUG,
1971 "IPv4 Binding failed, trying new port %d\n",
1972 ntohs (serverAddrv4.sin_port));
1977 GNUNET_NETWORK_socket_close (plugin->sockv4);
1978 plugin->sockv4 = NULL;
1982 if (plugin->sockv4 != NULL)
1984 addrs[sockets_created] = (struct sockaddr *) &serverAddrv4;
1985 addrlens[sockets_created] = sizeof (serverAddrv4);
1990 plugin->rs = GNUNET_NETWORK_fdset_create ();
1991 GNUNET_NETWORK_fdset_zero (plugin->rs);
1992 if (NULL != plugin->sockv4)
1993 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4);
1994 if (NULL != plugin->sockv6)
1995 GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6);
1997 plugin->select_task =
1998 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1999 GNUNET_SCHEDULER_NO_TASK,
2000 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
2001 NULL, &udp_plugin_select, plugin);
2004 /* create broadcast socket */
2007 plugin->sockv4_broadcast = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
2008 if (NULL == plugin->sockv4_broadcast)
2010 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
2014 #if HAVE_SOCKADDR_IN_SIN_LEN
2015 serverAddrv4.sin_len = sizeof (serverAddrv4);
2017 serverAddrv4.sin_family = AF_INET;
2018 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
2019 serverAddrv4.sin_port = htons (plugin->broadcast_port);
2020 addrlen = sizeof (serverAddrv4);
2021 serverAddr = (struct sockaddr *) &serverAddrv4;
2024 LOG (GNUNET_ERROR_TYPE_ERROR, "Binding Broadcast to IPv4 port %d\n",
2025 ntohs (serverAddrv4.sin_port));
2027 if (GNUNET_NETWORK_socket_bind (plugin->sockv4_broadcast, serverAddr, addrlen) != GNUNET_OK)
2029 GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast);
2030 plugin->sockv4_broadcast = NULL;
2032 if (plugin->sockv4_broadcast != NULL)
2034 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("UDP Broadcast sockets on port %u \n"), bport);
2036 if (GNUNET_NETWORK_socket_setsockopt (plugin->sockv4_broadcast, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int)) != GNUNET_OK)
2038 GNUNET_NETWORK_socket_close(plugin->sockv4_broadcast);
2039 plugin->sockv4_broadcast = NULL;
2043 plugin->broadcast_rs = GNUNET_NETWORK_fdset_create ();
2044 GNUNET_NETWORK_fdset_set (plugin->broadcast_rs, plugin->sockv4_broadcast);
2049 if (plugin->sockv4_broadcast != NULL)
2051 plugin->broadcast = GNUNET_YES;
2052 plugin->select_broadcast_task =
2053 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2054 GNUNET_SCHEDULER_NO_TASK,
2055 GNUNET_TIME_UNIT_FOREVER_REL, plugin->broadcast_rs,
2056 NULL, &udp_plugin_broadcast_select, plugin);
2058 plugin->send_broadcast_task = GNUNET_SCHEDULER_add_delayed(plugin->broadcast_interval, &udp_broadcast_send, plugin);
2061 plugin->broadcast = GNUNET_NO;
2064 if (sockets_created == 0)
2065 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
2067 GNUNET_NAT_register (env->cfg, GNUNET_NO, port, sockets_created,
2068 (const struct sockaddr **) addrs, addrlens,
2069 &udp_nat_port_map_callback, NULL, plugin);
2074 * Shutdown the plugin.
2076 * @param cls our 'struct GNUNET_TRANSPORT_PluginFunctions'
2080 libgnunet_plugin_transport_udp_done (void *cls)
2082 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2083 struct Plugin *plugin = api->cls;
2084 struct ReceiveContext *rc;
2086 /* FIXME: clean up heap and hashmap */
2087 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &destroy_session,
2089 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
2090 plugin->sessions = NULL;
2091 GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions, &destroy_inbound_session,
2093 GNUNET_CONTAINER_multihashmap_destroy (plugin->inbound_sessions);
2094 plugin->inbound_sessions = NULL;
2095 while (NULL != (rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags)))
2097 GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
2100 GNUNET_CONTAINER_heap_destroy (plugin->defrags);
2102 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
2104 GNUNET_SCHEDULER_cancel (plugin->select_task);
2105 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
2107 if (plugin->sockv4 != NULL)
2109 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
2110 plugin->sockv4 = NULL;
2112 if (plugin->sockv6 != NULL)
2114 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
2115 plugin->sockv6 = NULL;
2118 if (plugin->broadcast)
2120 if (plugin->select_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2122 GNUNET_SCHEDULER_cancel (plugin->select_broadcast_task);
2123 plugin->select_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2125 if (plugin->send_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2127 GNUNET_SCHEDULER_cancel (plugin->send_broadcast_task );
2128 plugin->send_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2131 if (plugin->sockv4_broadcast != NULL)
2133 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast));
2134 plugin->sockv4_broadcast = NULL;
2136 GNUNET_NETWORK_fdset_destroy (plugin->broadcast_rs);
2139 GNUNET_SERVER_mst_destroy (plugin->mst);
2140 GNUNET_NETWORK_fdset_destroy (plugin->rs);
2142 GNUNET_NAT_unregister (plugin->nat);
2144 GNUNET_free (plugin);
2149 /* end of plugin_transport_udp.c */