- nicer error msg
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
1 /*
2      This file is part of GNUnet
3      (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
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.
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      General Public License for more details.
14
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.
19 */
20
21 /**
22  * @file transport/plugin_transport_udp.c
23  * @brief Implementation of the UDP transport protocol
24  * @author Christian Grothoff
25  * @author Nathan Evans
26  * @author Matthias Wachs
27  */
28 #include "platform.h"
29 #include "plugin_transport_udp.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_fragmentation_lib.h"
33 #include "gnunet_nat_lib.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_resolver_service.h"
36 #include "gnunet_signatures.h"
37 #include "gnunet_constants.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet_transport_service.h"
40 #include "gnunet_transport_plugin.h"
41 #include "transport.h"
42
43 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
44
45
46 /**
47  * Number of messages we can defragment in parallel.  We only really
48  * defragment 1 message at a time, but if messages get re-ordered, we
49  * may want to keep knowledge about the previous message to avoid
50  * discarding the current message in favor of a single fragment of a
51  * previous message.  3 should be good since we don't expect massive
52  * message reorderings with UDP.
53  */
54 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
55
56 /**
57  * We keep a defragmentation queue per sender address.  How many
58  * sender addresses do we support at the same time? Memory consumption
59  * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this
60  * value. (So 128 corresponds to 12 MB and should suffice for
61  * connecting to roughly 128 peers via UDP).
62  */
63 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
64
65
66
67 /**
68  * Closure for 'append_port'.
69  */
70 struct PrettyPrinterContext
71 {
72   /**
73    * Function to call with the result.
74    */
75   GNUNET_TRANSPORT_AddressStringCallback asc;
76
77   /**
78    * Clsoure for 'asc'.
79    */
80   void *asc_cls;
81
82   /**
83    * Port to add after the IP address.
84    */
85   uint16_t port;
86 };
87
88 struct Session
89 {
90   /**
91    * Which peer is this session for?
92    */
93   struct GNUNET_PeerIdentity target;
94
95   /**
96    * Address of the other peer
97    */
98   const struct sockaddr *sock_addr;
99
100   size_t addrlen;
101
102   /**
103    * Desired delay for next sending we send to other peer
104    */
105   struct GNUNET_TIME_Relative flow_delay_for_other_peer;
106
107   /**
108    * Desired delay for next sending we received from other peer
109    */
110   struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
111
112   /**
113    * expected delay for ACKs
114    */
115   struct GNUNET_TIME_Relative last_expected_delay;
116
117
118   struct GNUNET_ATS_Information ats;
119
120   struct FragmentationContext * frag_ctx;
121 };
122
123
124 struct SessionCompareContext
125 {
126   struct Session *res;
127   const struct GNUNET_HELLO_Address *addr;
128 };
129
130
131 /**
132  * Closure for 'process_inbound_tokenized_messages'
133  */
134 struct SourceInformation
135 {
136   /**
137    * Sender identity.
138    */
139   struct GNUNET_PeerIdentity sender;
140
141   /**
142    * Source address.
143    */
144   const void *arg;
145
146   /**
147    * Number of bytes in source address.
148    */
149   size_t args;
150
151   struct Session *session;
152 };
153
154
155 /**
156  * Closure for 'find_receive_context'.
157  */
158 struct FindReceiveContext
159 {
160   /**
161    * Where to store the result.
162    */
163   struct DefragContext *rc;
164
165   /**
166    * Address to find.
167    */
168   const struct sockaddr *addr;
169
170   /**
171    * Number of bytes in 'addr'.
172    */
173   socklen_t addr_len;
174
175   struct Session *session;
176 };
177
178
179
180 /**
181  * Data structure to track defragmentation contexts based
182  * on the source of the UDP traffic.
183  */
184 struct DefragContext
185 {
186
187   /**
188    * Defragmentation context.
189    */
190   struct GNUNET_DEFRAGMENT_Context *defrag;
191
192   /**
193    * Source address this receive context is for (allocated at the
194    * end of the struct).
195    */
196   const struct sockaddr *src_addr;
197
198   /**
199    * Reference to master plugin struct.
200    */
201   struct Plugin *plugin;
202
203   /**
204    * Node in the defrag heap.
205    */
206   struct GNUNET_CONTAINER_HeapNode *hnode;
207
208   /**
209    * Length of 'src_addr'
210    */
211   size_t addr_len;
212 };
213
214
215
216 /**
217  * Closure for 'process_inbound_tokenized_messages'
218  */
219 struct FragmentationContext
220 {
221   struct FragmentationContext * next;
222   struct FragmentationContext * prev;
223
224   struct Plugin * plugin;
225   struct GNUNET_FRAGMENT_Context * frag;
226   struct Session * session;
227
228   struct GNUNET_TIME_Absolute timeout;
229
230
231   /**
232    * Function to call upon completion of the transmission.
233    */
234   GNUNET_TRANSPORT_TransmitContinuation cont;
235
236   /**
237    * Closure for 'cont'.
238    */
239   void *cont_cls;
240
241   size_t bytes_to_send;
242 };
243
244
245 struct UDPMessageWrapper
246 {
247   struct Session *session;
248   struct UDPMessageWrapper *prev;
249   struct UDPMessageWrapper *next;
250   char *udp;
251   size_t msg_size;
252
253   struct GNUNET_TIME_Absolute timeout;
254
255   /**
256    * Function to call upon completion of the transmission.
257    */
258   GNUNET_TRANSPORT_TransmitContinuation cont;
259
260   /**
261    * Closure for 'cont'.
262    */
263   void *cont_cls;
264
265   struct FragmentationContext *frag_ctx;
266
267 };
268
269
270 /**
271  * UDP ACK Message-Packet header (after defragmentation).
272  */
273 struct UDP_ACK_Message
274 {
275   /**
276    * Message header.
277    */
278   struct GNUNET_MessageHeader header;
279
280   /**
281    * Desired delay for flow control
282    */
283   uint32_t delay;
284
285   /**
286    * What is the identity of the sender
287    */
288   struct GNUNET_PeerIdentity sender;
289
290 };
291
292
293
294 /**
295  * Function called for a quick conversion of the binary address to
296  * a numeric address.  Note that the caller must not free the
297  * address and that the next call to this function is allowed
298  * to override the address again.
299  *
300  * @param cls closure
301  * @param addr binary address
302  * @param addrlen length of the address
303  * @return string representing the same address
304  */
305 const char *
306 udp_address_to_string (void *cls, const void *addr, size_t addrlen)
307 {
308   static char rbuf[INET6_ADDRSTRLEN + 10];
309   char buf[INET6_ADDRSTRLEN];
310   const void *sb;
311   struct in_addr a4;
312   struct in6_addr a6;
313   const struct IPv4UdpAddress *t4;
314   const struct IPv6UdpAddress *t6;
315   int af;
316   uint16_t port;
317
318   if (addrlen == sizeof (struct IPv6UdpAddress))
319   {
320     t6 = addr;
321     af = AF_INET6;
322     port = ntohs (t6->u6_port);
323     memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
324     sb = &a6;
325   }
326   else if (addrlen == sizeof (struct IPv4UdpAddress))
327   {
328     t4 = addr;
329     af = AF_INET;
330     port = ntohs (t4->u4_port);
331     memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
332     sb = &a4;
333   }
334   else
335   {
336     GNUNET_break_op (0);
337     return NULL;
338   }
339   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
340   GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
341                    buf, port);
342   return rbuf;
343 }
344
345
346 /**
347  * Append our port and forward the result.
348  *
349  * @param cls a 'struct PrettyPrinterContext'
350  * @param hostname result from DNS resolver
351  */
352 static void
353 append_port (void *cls, const char *hostname)
354 {
355   struct PrettyPrinterContext *ppc = cls;
356   char *ret;
357
358   if (hostname == NULL)
359   {
360     ppc->asc (ppc->asc_cls, NULL);
361     GNUNET_free (ppc);
362     return;
363   }
364   GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
365   ppc->asc (ppc->asc_cls, ret);
366   GNUNET_free (ret);
367 }
368
369
370 /**
371  * Convert the transports address to a nice, human-readable
372  * format.
373  *
374  * @param cls closure
375  * @param type name of the transport that generated the address
376  * @param addr one of the addresses of the host, NULL for the last address
377  *        the specific address format depends on the transport
378  * @param addrlen length of the address
379  * @param numeric should (IP) addresses be displayed in numeric form?
380  * @param timeout after how long should we give up?
381  * @param asc function to call on each string
382  * @param asc_cls closure for asc
383  */
384 static void
385 udp_plugin_address_pretty_printer (void *cls, const char *type,
386                                    const void *addr, size_t addrlen,
387                                    int numeric,
388                                    struct GNUNET_TIME_Relative timeout,
389                                    GNUNET_TRANSPORT_AddressStringCallback asc,
390                                    void *asc_cls)
391 {
392   struct PrettyPrinterContext *ppc;
393   const void *sb;
394   size_t sbs;
395   struct sockaddr_in a4;
396   struct sockaddr_in6 a6;
397   const struct IPv4UdpAddress *u4;
398   const struct IPv6UdpAddress *u6;
399   uint16_t port;
400
401   if (addrlen == sizeof (struct IPv6UdpAddress))
402   {
403     u6 = addr;
404     memset (&a6, 0, sizeof (a6));
405     a6.sin6_family = AF_INET6;
406 #if HAVE_SOCKADDR_IN_SIN_LEN
407     a6.sin6_len = sizeof (a6);
408 #endif
409     a6.sin6_port = u6->u6_port;
410     memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
411     port = ntohs (u6->u6_port);
412     sb = &a6;
413     sbs = sizeof (a6);
414   }
415   else if (addrlen == sizeof (struct IPv4UdpAddress))
416   {
417     u4 = addr;
418     memset (&a4, 0, sizeof (a4));
419     a4.sin_family = AF_INET;
420 #if HAVE_SOCKADDR_IN_SIN_LEN
421     a4.sin_len = sizeof (a4);
422 #endif
423     a4.sin_port = u4->u4_port;
424     a4.sin_addr.s_addr = u4->ipv4_addr;
425     port = ntohs (u4->u4_port);
426     sb = &a4;
427     sbs = sizeof (a4);
428   }
429   else
430   {
431     /* invalid address */
432     GNUNET_break_op (0);
433     asc (asc_cls, NULL);
434     return;
435   }
436   ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
437   ppc->asc = asc;
438   ppc->asc_cls = asc_cls;
439   ppc->port = port;
440   GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
441 }
442
443
444 /**
445  * Check if the given port is plausible (must be either our listen
446  * port or our advertised port).  If it is neither, we return
447  * GNUNET_SYSERR.
448  *
449  * @param plugin global variables
450  * @param in_port port number to check
451  * @return GNUNET_OK if port is either open_port or adv_port
452  */
453 static int
454 check_port (struct Plugin *plugin, uint16_t in_port)
455 {
456   if ((in_port == plugin->port) || (in_port == plugin->aport))
457     return GNUNET_OK;
458   return GNUNET_SYSERR;
459 }
460
461
462
463 /**
464  * Function that will be called to check if a binary address for this
465  * plugin is well-formed and corresponds to an address for THIS peer
466  * (as per our configuration).  Naturally, if absolutely necessary,
467  * plugins can be a bit conservative in their answer, but in general
468  * plugins should make sure that the address does not redirect
469  * traffic to a 3rd party that might try to man-in-the-middle our
470  * traffic.
471  *
472  * @param cls closure, should be our handle to the Plugin
473  * @param addr pointer to the address
474  * @param addrlen length of addr
475  * @return GNUNET_OK if this is a plausible address for this peer
476  *         and transport, GNUNET_SYSERR if not
477  *
478  */
479 static int
480 udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
481 {
482   struct Plugin *plugin = cls;
483   struct IPv4UdpAddress *v4;
484   struct IPv6UdpAddress *v6;
485
486   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
487       (addrlen != sizeof (struct IPv6UdpAddress)))
488   {
489     GNUNET_break_op (0);
490     return GNUNET_SYSERR;
491   }
492   if (addrlen == sizeof (struct IPv4UdpAddress))
493   {
494     v4 = (struct IPv4UdpAddress *) addr;
495     if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
496       return GNUNET_SYSERR;
497     if (GNUNET_OK !=
498         GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
499                                  sizeof (struct in_addr)))
500       return GNUNET_SYSERR;
501   }
502   else
503   {
504     v6 = (struct IPv6UdpAddress *) addr;
505     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
506     {
507       GNUNET_break_op (0);
508       return GNUNET_SYSERR;
509     }
510     if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
511       return GNUNET_SYSERR;
512     if (GNUNET_OK !=
513         GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
514                                  sizeof (struct in6_addr)))
515       return GNUNET_SYSERR;
516   }
517   return GNUNET_OK;
518 }
519
520
521 /**
522  * Destroy a session, plugin is being unloaded.
523  *
524  * @param cls unused
525  * @param key hash of public key of target peer
526  * @param value a 'struct PeerSession*' to clean up
527  * @return GNUNET_OK (continue to iterate)
528  */
529 static int
530 disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
531 {
532   struct Plugin *plugin = cls;
533   struct Session *s = value;
534   struct UDPMessageWrapper *udpw;
535
536 #if DEBUG_UDP
537   LOG (GNUNET_ERROR_TYPE_DEBUG,
538        "Session %p to peer `%s' address ended \n",
539          s,
540          GNUNET_i2s (&s->target),
541          GNUNET_a2s (s->sock_addr, s->addrlen));
542 #endif
543   plugin->env->session_end (plugin->env->cls, &s->target, s);
544
545   if (s->frag_ctx != NULL)
546   {
547     GNUNET_FRAGMENT_context_destroy(s->frag_ctx->frag);
548     GNUNET_free (s->frag_ctx);
549     s->frag_ctx = NULL;
550   }
551
552   udpw = plugin->msg_head;
553   while (udpw != NULL)
554   {
555     if (udpw->session == s)
556     {
557       GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
558
559       if (udpw->cont != NULL)
560         udpw->cont (udpw->cont_cls, &s->target, GNUNET_SYSERR);
561       GNUNET_free (udpw);
562     }
563     udpw = plugin->msg_head;
564   }
565
566   GNUNET_assert (GNUNET_YES ==
567                  GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
568                                                        &s->target.hashPubKey,
569                                                        s));
570
571
572   GNUNET_free (s);
573   return GNUNET_OK;
574 }
575
576
577 /**
578  * Disconnect from a remote node.  Clean up session if we have one for this peer
579  *
580  * @param cls closure for this call (should be handle to Plugin)
581  * @param target the peeridentity of the peer to disconnect
582  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
583  */
584 static void
585 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
586 {
587   struct Plugin *plugin = cls;
588   GNUNET_assert (plugin != NULL);
589
590   GNUNET_assert (target != NULL);
591 #if DEBUG_UDP
592   LOG (GNUNET_ERROR_TYPE_DEBUG,
593        "Disconnecting from peer `%s'\n", GNUNET_i2s (target));
594 #endif
595   /* Clean up sessions */
596   GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessions, &target->hashPubKey, &disconnect_and_free_it, plugin);
597 }
598
599 static struct Session *
600 create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
601                 const void *addr, size_t addrlen,
602                 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
603 {
604   struct Session *s;
605   const struct IPv4UdpAddress *t4;
606   const struct IPv6UdpAddress *t6;
607   struct sockaddr_in *v4;
608   struct sockaddr_in6 *v6;
609   size_t len;
610
611   switch (addrlen)
612   {
613   case sizeof (struct IPv4UdpAddress):
614     if (NULL == plugin->sockv4)
615     {
616       return NULL;
617     }
618     t4 = addr;
619     s = GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in));
620     len = sizeof (struct sockaddr_in);
621     v4 = (struct sockaddr_in *) &s[1];
622     v4->sin_family = AF_INET;
623 #if HAVE_SOCKADDR_IN_SIN_LEN
624     v4->sin_len = sizeof (struct sockaddr_in);
625 #endif
626     v4->sin_port = t4->u4_port;
627     v4->sin_addr.s_addr = t4->ipv4_addr;
628     s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v4, sizeof (struct sockaddr_in));
629     break;
630   case sizeof (struct IPv6UdpAddress):
631     if (NULL == plugin->sockv6)
632     {
633       return NULL;
634     }
635     t6 = addr;
636     s =
637         GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6));
638     len = sizeof (struct sockaddr_in6);
639     v6 = (struct sockaddr_in6 *) &s[1];
640     v6->sin6_family = AF_INET6;
641 #if HAVE_SOCKADDR_IN_SIN_LEN
642     v6->sin6_len = sizeof (struct sockaddr_in6);
643 #endif
644     v6->sin6_port = t6->u6_port;
645     v6->sin6_addr = t6->ipv6_addr;
646     s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v6, sizeof (struct sockaddr_in6));
647     break;
648   default:
649     /* Must have a valid address to send to */
650     GNUNET_break_op (0);
651     return NULL;
652   }
653
654   s->addrlen = len;
655   s->target = *target;
656   s->sock_addr = (const struct sockaddr *) &s[1];
657   s->flow_delay_for_other_peer = GNUNET_TIME_relative_get_zero();
658   s->flow_delay_from_other_peer = GNUNET_TIME_absolute_get_zero();
659   s->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
660
661   return s;
662 }
663
664 static int session_cmp_it (void *cls,
665                            const GNUNET_HashCode * key,
666                            void *value)
667 {
668   struct SessionCompareContext * cctx = cls;
669   const struct GNUNET_HELLO_Address *address = cctx->addr;
670   struct Session *s = value;
671
672   socklen_t s_addrlen = s->addrlen;
673
674 #if VERBOSE_UDP
675   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing  address %s <-> %s\n",
676       udp_address_to_string (NULL, (void *) address->address, address->address_length),
677       GNUNET_a2s (s->sock_addr, s->addrlen));
678 #endif
679
680   if ((address->address_length == sizeof (struct IPv4UdpAddress)) &&
681       (s_addrlen == sizeof (struct sockaddr_in)))
682   {
683     struct IPv4UdpAddress * u4 = NULL;
684     u4 = (struct IPv4UdpAddress *) address->address;
685     const struct sockaddr_in *s4 = (const struct sockaddr_in *) s->sock_addr;
686     if ((0 == memcmp ((const void *) &u4->ipv4_addr,(const void *) &s4->sin_addr, sizeof (struct in_addr))) &&
687         (u4->u4_port == s4->sin_port))
688     {
689       cctx->res = s;
690       return GNUNET_NO;
691     }
692
693   }
694   if ((address->address_length == sizeof (struct IPv6UdpAddress)) &&
695       (s_addrlen == sizeof (struct sockaddr_in6)))
696   {
697     struct IPv6UdpAddress * u6 = NULL;
698     u6 = (struct IPv6UdpAddress *) address->address;
699     const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) s->sock_addr;
700     if ((0 == memcmp (&u6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr))) &&
701         (u6->u6_port == s6->sin6_port))
702     {
703       cctx->res = s;
704       return GNUNET_NO;
705     }
706   }
707
708
709   return GNUNET_YES;
710 }
711
712
713 /**
714  * Creates a new outbound session the transport service will use to send data to the
715  * peer
716  *
717  * @param cls the plugin
718  * @param address the address
719  * @return the session or NULL of max connections exceeded
720  */
721 static struct Session *
722 udp_plugin_get_session (void *cls,
723                   const struct GNUNET_HELLO_Address *address)
724 {
725   struct Session * s = NULL;
726   struct Plugin * plugin = cls;
727
728   GNUNET_assert (plugin != NULL);
729   GNUNET_assert (address != NULL);
730
731   if ((address->address == NULL) ||
732       ((address->address_length != sizeof (struct IPv4UdpAddress)) &&
733       (address->address_length != sizeof (struct IPv6UdpAddress))))
734   {
735     GNUNET_break (0);
736     return NULL;
737   }
738
739   /* check if session already exists */
740   struct SessionCompareContext cctx;
741   cctx.addr = address;
742   cctx.res = NULL;
743 #if VERBOSE_UDP
744   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for existing session for peer `%s' `%s' \n", GNUNET_i2s (&address->peer), udp_address_to_string(NULL, address->address, address->address_length));
745 #endif
746   GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessions, &address->peer.hashPubKey, session_cmp_it, &cctx);
747   if (cctx.res != NULL)
748   {
749 #if VERBOSE_UDP
750     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
751 #endif
752     return cctx.res;
753   }
754
755   /* otherwise create new */
756   s = create_session (plugin,
757       &address->peer,
758       address->address,
759       address->address_length,
760       NULL, NULL);
761 #if VERBOSE
762     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763               "Creating new session %p for peer `%s' address `%s'\n",
764               s,
765               GNUNET_i2s(&address->peer),
766               udp_address_to_string(NULL,address->address,address->address_length));
767 #endif
768   GNUNET_assert (GNUNET_OK ==
769                  GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
770                                                     &s->target.hashPubKey,
771                                                     s,
772                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
773
774   return s;
775 }
776
777 /**
778  * Function that is called with messages created by the fragmentation
779  * module.  In the case of the 'proc' callback of the
780  * GNUNET_FRAGMENT_context_create function, this function must
781  * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
782  *
783  * @param cls closure, the 'struct FragmentationContext'
784  * @param msg the message that was created
785  */
786 static void
787 enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
788 {
789   struct FragmentationContext *frag_ctx = cls;
790   struct Plugin *plugin = frag_ctx->plugin;
791   struct UDPMessageWrapper * udpw;
792
793   size_t msg_len = ntohs (msg->size);
794
795 #if VERBOSE_UDP
796   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %u bytes %u\n", msg_len , sizeof (struct UDPMessageWrapper));
797 #endif
798
799   udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msg_len);
800   udpw->session = frag_ctx->session;
801   udpw->udp = (char *) &udpw[1];
802
803   udpw->msg_size = msg_len;
804   udpw->cont = frag_ctx->cont;
805   udpw->cont_cls = frag_ctx->cont_cls;
806   udpw->timeout = frag_ctx->timeout;
807   udpw->frag_ctx = frag_ctx;
808   memcpy (udpw->udp, msg, msg_len);
809
810   GNUNET_CONTAINER_DLL_insert(plugin->msg_head, plugin->msg_tail, udpw);
811 }
812
813
814 /**
815  * Function that can be used by the transport service to transmit
816  * a message using the plugin.   Note that in the case of a
817  * peer disconnecting, the continuation MUST be called
818  * prior to the disconnect notification itself.  This function
819  * will be called with this peer's HELLO message to initiate
820  * a fresh connection to another peer.
821  *
822  * @param cls closure
823  * @param s which session must be used
824  * @param msgbuf the message to transmit
825  * @param msgbuf_size number of bytes in 'msgbuf'
826  * @param priority how important is the message (most plugins will
827  *                 ignore message priority and just FIFO)
828  * @param to how long to wait at most for the transmission (does not
829  *                require plugins to discard the message after the timeout,
830  *                just advisory for the desired delay; most plugins will ignore
831  *                this as well)
832  * @param cont continuation to call once the message has
833  *        been transmitted (or if the transport is ready
834  *        for the next transmission call; or if the
835  *        peer disconnected...); can be NULL
836  * @param cont_cls closure for cont
837  * @return number of bytes used (on the physical network, with overheads);
838  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
839  *         and does NOT mean that the message was not transmitted (DV)
840  */
841 static ssize_t
842 udp_plugin_send (void *cls,
843                   struct Session *s,
844                   const char *msgbuf, size_t msgbuf_size,
845                   unsigned int priority,
846                   struct GNUNET_TIME_Relative to,
847                   GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
848 {
849   struct Plugin *plugin = cls;
850   size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
851
852   struct UDPMessageWrapper * udpw;
853   struct UDPMessage *udp;
854   char mbuf[mlen];
855   GNUNET_assert (plugin != NULL);
856   GNUNET_assert (s != NULL);
857
858   if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
859   {
860     GNUNET_break (0);
861     return GNUNET_SYSERR;
862   }
863
864   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value(plugin->sessions, &s->target.hashPubKey, s))
865   {
866     GNUNET_break (0);
867     return GNUNET_SYSERR;
868   }
869
870   LOG (GNUNET_ERROR_TYPE_DEBUG,
871        "UDP transmits %u-byte message to `%s' using address `%s'\n",
872          msgbuf_size,
873          GNUNET_i2s (&s->target),
874          GNUNET_a2s(s->sock_addr, s->addrlen));
875
876   /* Message */
877   udp = (struct UDPMessage *) mbuf;
878   udp->header.size = htons (mlen);
879   udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
880   udp->reserved = htonl (0);
881   udp->sender = *plugin->env->my_identity;
882
883   if (mlen <= UDP_MTU)
884   {
885     udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + mlen);
886     udpw->session = s;
887     udpw->udp = (char *) &udpw[1];
888     udpw->msg_size = mlen;
889     udpw->timeout = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), to);
890     udpw->cont = cont;
891     udpw->cont_cls = cont_cls;
892     udpw->frag_ctx = NULL;
893
894     memcpy (udpw->udp, udp, sizeof (struct UDPMessage));
895     memcpy (&udpw->udp[sizeof (struct UDPMessage)], msgbuf, msgbuf_size);
896
897     GNUNET_CONTAINER_DLL_insert(plugin->msg_head, plugin->msg_tail, udpw);
898   }
899   else
900   {
901     LOG (GNUNET_ERROR_TYPE_DEBUG,
902          "UDP has to fragment message \n");
903     if  (s->frag_ctx != NULL)
904       return GNUNET_SYSERR;
905     memcpy (&udp[1], msgbuf, msgbuf_size);
906     struct FragmentationContext * frag_ctx = GNUNET_malloc(sizeof (struct FragmentationContext));
907
908     frag_ctx->plugin = plugin;
909     frag_ctx->session = s;
910     frag_ctx->cont = cont;
911     frag_ctx->cont_cls = cont_cls;
912     frag_ctx->timeout = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), to);
913     frag_ctx->bytes_to_send = mlen;
914     frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
915               UDP_MTU,
916               &plugin->tracker,
917               s->last_expected_delay,
918               &udp->header,
919               &enqueue_fragment,
920               frag_ctx);
921
922     s->frag_ctx = frag_ctx;
923
924   }
925   return mlen;
926 }
927
928
929 /**
930  * Our external IP address/port mapping has changed.
931  *
932  * @param cls closure, the 'struct LocalAddrList'
933  * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
934  *     the previous (now invalid) one
935  * @param addr either the previous or the new public IP address
936  * @param addrlen actual lenght of the address
937  */
938 static void
939 udp_nat_port_map_callback (void *cls, int add_remove,
940                            const struct sockaddr *addr, socklen_t addrlen)
941 {
942   struct Plugin *plugin = cls;
943   struct IPv4UdpAddress u4;
944   struct IPv6UdpAddress u6;
945   void *arg;
946   size_t args;
947
948   /* convert 'addr' to our internal format */
949   switch (addr->sa_family)
950   {
951   case AF_INET:
952     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
953     u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
954     u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
955     arg = &u4;
956     args = sizeof (u4);
957     break;
958   case AF_INET6:
959     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
960     memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
961             sizeof (struct in6_addr));
962     u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
963     arg = &u6;
964     args = sizeof (u6);
965     break;
966   default:
967     GNUNET_break (0);
968     return;
969   }
970   /* modify our published address list */
971   plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
972 }
973
974
975
976 /**
977  * Message tokenizer has broken up an incomming message. Pass it on
978  * to the service.
979  *
980  * @param cls the 'struct Plugin'
981  * @param client the 'struct SourceInformation'
982  * @param hdr the actual message
983  */
984 static void
985 process_inbound_tokenized_messages (void *cls, void *client,
986                                     const struct GNUNET_MessageHeader *hdr)
987 {
988   struct Plugin *plugin = cls;
989   struct SourceInformation *si = client;
990   struct GNUNET_ATS_Information ats[2];
991   struct GNUNET_TIME_Relative delay;
992
993   GNUNET_assert (si->session != NULL);
994   /* setup ATS */
995   ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
996   ats[0].value = htonl (1);
997   ats[1] = si->session->ats;
998   GNUNET_break (ntohl(ats[1].value) != GNUNET_ATS_NET_UNSPECIFIED);
999
1000   delay = plugin->env->receive (plugin->env->cls,
1001                 &si->sender,
1002                 hdr,
1003                 (const struct GNUNET_ATS_Information *) &ats, 2,
1004                 NULL,
1005                 si->arg,
1006                 si->args);
1007   si->session->flow_delay_for_other_peer = delay;
1008 }
1009
1010
1011 /**
1012  * We've received a UDP Message.  Process it (pass contents to main service).
1013  *
1014  * @param plugin plugin context
1015  * @param msg the message
1016  * @param sender_addr sender address
1017  * @param sender_addr_len number of bytes in sender_addr
1018  */
1019 static void
1020 process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1021                      const struct sockaddr *sender_addr,
1022                      socklen_t sender_addr_len)
1023 {
1024   struct SourceInformation si;
1025   struct Session * s = NULL;
1026   struct IPv4UdpAddress u4;
1027   struct IPv6UdpAddress u6;
1028   struct GNUNET_ATS_Information ats;
1029   const void *arg;
1030   size_t args;
1031
1032   if (0 != ntohl (msg->reserved))
1033   {
1034     GNUNET_break_op (0);
1035     return;
1036   }
1037   if (ntohs (msg->header.size) <
1038       sizeof (struct GNUNET_MessageHeader) + sizeof (struct UDPMessage))
1039   {
1040     GNUNET_break_op (0);
1041     return;
1042   }
1043
1044   ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
1045   ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED);
1046   /* convert address */
1047   switch (sender_addr->sa_family)
1048   {
1049   case AF_INET:
1050     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in));
1051     u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr;
1052     u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port;
1053     arg = &u4;
1054     args = sizeof (u4);
1055     break;
1056   case AF_INET6:
1057     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in6));
1058     u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr;
1059     u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port;
1060     arg = &u6;
1061     args = sizeof (u6);
1062     break;
1063   default:
1064     GNUNET_break (0);
1065     return;
1066   }
1067 #if DEBUG_UDP
1068   LOG (GNUNET_ERROR_TYPE_DEBUG,
1069        "Received message with %u bytes from peer `%s' at `%s'\n",
1070        (unsigned int) ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1071        GNUNET_a2s (sender_addr, sender_addr_len));
1072 #endif
1073
1074   struct GNUNET_HELLO_Address * address = GNUNET_HELLO_address_allocate(&msg->sender, "udp", arg, args);
1075   s = udp_plugin_get_session(plugin, address);
1076   GNUNET_free (address);
1077
1078   /* iterate over all embedded messages */
1079   si.session = s;
1080   si.sender = msg->sender;
1081   si.arg = arg;
1082   si.args = args;
1083
1084   GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
1085                              ntohs (msg->header.size) -
1086                              sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
1087 }
1088
1089
1090 /**
1091  * Scan the heap for a receive context with the given address.
1092  *
1093  * @param cls the 'struct FindReceiveContext'
1094  * @param node internal node of the heap
1095  * @param element value stored at the node (a 'struct ReceiveContext')
1096  * @param cost cost associated with the node
1097  * @return GNUNET_YES if we should continue to iterate,
1098  *         GNUNET_NO if not.
1099  */
1100 static int
1101 find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
1102                       void *element, GNUNET_CONTAINER_HeapCostType cost)
1103 {
1104   struct FindReceiveContext *frc = cls;
1105   struct DefragContext *e = element;
1106
1107   if ((frc->addr_len == e->addr_len) &&
1108       (0 == memcmp (frc->addr, e->src_addr, frc->addr_len)))
1109   {
1110     frc->rc = e;
1111     return GNUNET_NO;
1112   }
1113   return GNUNET_YES;
1114 }
1115
1116
1117 /**
1118  * Process a defragmented message.
1119  *
1120  * @param cls the 'struct ReceiveContext'
1121  * @param msg the message
1122  */
1123 static void
1124 fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1125 {
1126   struct DefragContext *rc = cls;
1127
1128   if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
1129   {
1130     GNUNET_break (0);
1131     return;
1132   }
1133   if (ntohs (msg->size) < sizeof (struct UDPMessage))
1134   {
1135     GNUNET_break (0);
1136     return;
1137   }
1138   process_udp_message (rc->plugin, (const struct UDPMessage *) msg,
1139                        rc->src_addr, rc->addr_len);
1140 }
1141
1142 struct LookupContext
1143 {
1144   const struct sockaddr * addr;
1145   size_t addrlen;
1146
1147   struct Session *res;
1148 };
1149
1150 static int
1151 lookup_session_by_addr_it (void *cls, const GNUNET_HashCode * key, void *value)
1152 {
1153   struct LookupContext *l_ctx = cls;
1154   struct Session * s = value;
1155
1156   if ((s->addrlen == l_ctx->addrlen) &&
1157       (0 == memcmp (s->sock_addr, l_ctx->addr, s->addrlen)))
1158   {
1159     l_ctx->res = s;
1160     return GNUNET_NO;
1161   }
1162   return GNUNET_YES;
1163 }
1164
1165 /**
1166  * Transmit an acknowledgement.
1167  *
1168  * @param cls the 'struct ReceiveContext'
1169  * @param id message ID (unused)
1170  * @param msg ack to transmit
1171  */
1172 static void
1173 ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
1174 {
1175   struct DefragContext *rc = cls;
1176
1177   size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size);
1178   struct UDP_ACK_Message *udp_ack;
1179   uint32_t delay = 0;
1180   struct UDPMessageWrapper *udpw;
1181   struct Session *s;
1182
1183   struct LookupContext l_ctx;
1184   l_ctx.addr = rc->src_addr;
1185   l_ctx.addrlen = rc->addr_len;
1186   l_ctx.res = NULL;
1187   GNUNET_CONTAINER_multihashmap_iterate (rc->plugin->sessions,
1188       &lookup_session_by_addr_it,
1189       &l_ctx);
1190   s = l_ctx.res;
1191
1192   GNUNET_assert (s != NULL);
1193
1194   if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
1195     delay = s->flow_delay_for_other_peer.rel_value;
1196
1197 #if DEBUG_UDP
1198   LOG (GNUNET_ERROR_TYPE_DEBUG,
1199        "Sending ACK to `%s' including delay of %u ms\n",
1200        GNUNET_a2s (rc->src_addr,
1201                    (rc->src_addr->sa_family ==
1202                     AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct
1203                                                                      sockaddr_in6)),
1204        delay);
1205 #endif
1206   udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msize);
1207   udpw->cont = NULL;
1208   udpw->cont_cls = NULL;
1209   udpw->frag_ctx = NULL;
1210   udpw->msg_size = msize;
1211   udpw->session = s;
1212   udpw->timeout = GNUNET_TIME_absolute_get_forever();
1213   udpw->udp = (char *)&udpw[1];
1214
1215   udp_ack = (struct UDP_ACK_Message *) udpw->udp;
1216   udp_ack->header.size = htons ((uint16_t) msize);
1217   udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
1218   udp_ack->delay = htonl (delay);
1219   udp_ack->sender = *rc->plugin->env->my_identity;
1220   memcpy (&udp_ack[1], msg, ntohs (msg->size));
1221
1222   GNUNET_CONTAINER_DLL_insert(rc->plugin->msg_head, rc->plugin->msg_tail, udpw);
1223 }
1224
1225
1226 static void read_process_msg (struct Plugin *plugin,
1227     const struct GNUNET_MessageHeader *msg,
1228     char *addr,
1229     socklen_t fromlen)
1230 {
1231   if (ntohs (msg->size) < sizeof (struct UDPMessage))
1232   {
1233     GNUNET_break_op (0);
1234     return;
1235   }
1236   process_udp_message (plugin, (const struct UDPMessage *) msg,
1237                        (const struct sockaddr *) addr, fromlen);
1238   return;
1239 }
1240
1241 static void read_process_ack (struct Plugin *plugin,
1242     const struct GNUNET_MessageHeader *msg,
1243     char *addr,
1244     socklen_t fromlen)
1245 {
1246   const struct GNUNET_MessageHeader *ack;
1247   const struct UDP_ACK_Message *udp_ack;
1248   struct LookupContext l_ctx;
1249   struct Session *s = NULL;
1250   struct GNUNET_TIME_Relative flow_delay;
1251
1252   if (ntohs (msg->size) <
1253       sizeof (struct UDP_ACK_Message) + sizeof (struct GNUNET_MessageHeader))
1254   {
1255     GNUNET_break_op (0);
1256     return;
1257   }
1258
1259   udp_ack = (const struct UDP_ACK_Message *) msg;
1260
1261   l_ctx.addr = (const struct sockaddr *) addr;
1262   l_ctx.addrlen = fromlen;
1263   l_ctx.res = NULL;
1264   GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions,
1265       &lookup_session_by_addr_it,
1266       &l_ctx);
1267   s = l_ctx.res;
1268
1269   if ((s == NULL) || (s->frag_ctx == NULL))
1270     return;
1271
1272   flow_delay.rel_value = (uint64_t) ntohl (udp_ack->delay);
1273   LOG (GNUNET_ERROR_TYPE_DEBUG, "We received a sending delay of %llu\n",
1274        flow_delay.rel_value);
1275   s->flow_delay_from_other_peer =
1276       GNUNET_TIME_relative_to_absolute (flow_delay);
1277
1278   ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
1279   if (ntohs (ack->size) !=
1280       ntohs (msg->size) - sizeof (struct UDP_ACK_Message))
1281   {
1282     GNUNET_break_op (0);
1283     return;
1284   }
1285
1286   if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, ack))
1287   {
1288 #if DEBUG_UDP
1289   LOG (GNUNET_ERROR_TYPE_DEBUG,
1290        "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
1291        (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1292        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1293 #endif
1294     return;
1295   }
1296
1297 #if DEBUG_UDP
1298   LOG (GNUNET_ERROR_TYPE_DEBUG,
1299        "FULL MESSAGE ACKed\n",
1300        (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1301        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1302 #endif
1303   s->last_expected_delay = GNUNET_FRAGMENT_context_destroy (s->frag_ctx->frag);
1304
1305   struct UDPMessageWrapper * udpw = plugin->msg_head;
1306   while (udpw!= NULL)
1307   {
1308     if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == s->frag_ctx))
1309     {
1310       GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1311       GNUNET_free (udpw);
1312     }
1313     udpw = udpw->next;
1314   }
1315
1316   if (s->frag_ctx->cont != NULL)
1317     s->frag_ctx->cont
1318     (s->frag_ctx->cont_cls, &udp_ack->sender, GNUNET_OK);
1319   GNUNET_free (s->frag_ctx);
1320   s->frag_ctx = NULL;
1321   return;
1322 }
1323
1324 static void read_process_fragment (struct Plugin *plugin,
1325     const struct GNUNET_MessageHeader *msg,
1326     char *addr,
1327     socklen_t fromlen)
1328 {
1329   struct DefragContext *d_ctx;
1330   struct GNUNET_TIME_Absolute now;
1331   struct FindReceiveContext frc;
1332
1333
1334   frc.rc = NULL;
1335   frc.addr = (const struct sockaddr *) addr;
1336   frc.addr_len = fromlen;
1337
1338 #if DEBUG_UDP
1339   LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
1340        (unsigned int) ntohs (msg->size),
1341        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1342 #endif
1343
1344   /* Lookup existing receive context for this address */
1345   GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
1346                                  &find_receive_context,
1347                                  &frc);
1348   now = GNUNET_TIME_absolute_get ();
1349   d_ctx = frc.rc;
1350
1351   if (d_ctx == NULL)
1352   {
1353     /* Create a new defragmentation context */
1354     d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + fromlen);
1355     memcpy (&d_ctx[1], addr, fromlen);
1356     d_ctx->src_addr = (const struct sockaddr *) &d_ctx[1];
1357     d_ctx->addr_len = fromlen;
1358     d_ctx->plugin = plugin;
1359     d_ctx->defrag =
1360         GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1361                                           UDP_MAX_MESSAGES_IN_DEFRAG, d_ctx,
1362                                           &fragment_msg_proc, &ack_proc);
1363     d_ctx->hnode =
1364         GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx,
1365                                       (GNUNET_CONTAINER_HeapCostType)
1366                                       now.abs_value);
1367 #if DEBUG_UDP
1368   LOG (GNUNET_ERROR_TYPE_DEBUG, "Created new defragmentation context for %u-byte fragment from `%s'\n",
1369        (unsigned int) ntohs (msg->size),
1370        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1371 #endif
1372   }
1373   else
1374   {
1375 #if DEBUG_UDP
1376   LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing defragmentation context for %u-byte fragment from `%s'\n",
1377        (unsigned int) ntohs (msg->size),
1378        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1379 #endif
1380   }
1381
1382   if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg))
1383   {
1384     /* keep this 'rc' from expiring */
1385     GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, d_ctx->hnode,
1386                                        (GNUNET_CONTAINER_HeapCostType)
1387                                        now.abs_value);
1388   }
1389   if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
1390       UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1391   {
1392     /* remove 'rc' that was inactive the longest */
1393     d_ctx = GNUNET_CONTAINER_heap_remove_root (plugin->defrag_ctxs);
1394     GNUNET_assert (NULL != d_ctx);
1395     GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag);
1396     GNUNET_free (d_ctx);
1397   }
1398 }
1399
1400 /**
1401  * Read and process a message from the given socket.
1402  *
1403  * @param plugin the overall plugin
1404  * @param rsock socket to read from
1405  */
1406 static void
1407 udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1408 {
1409   socklen_t fromlen;
1410   char addr[32];
1411   char buf[65536];
1412   ssize_t size;
1413   const struct GNUNET_MessageHeader *msg;
1414
1415   fromlen = sizeof (addr);
1416   memset (&addr, 0, sizeof (addr));
1417   size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1418                                       (struct sockaddr *) &addr, &fromlen);
1419
1420   if (size < sizeof (struct GNUNET_MessageHeader))
1421   {
1422     GNUNET_break_op (0);
1423     return;
1424   }
1425   msg = (const struct GNUNET_MessageHeader *) buf;
1426
1427   LOG (GNUNET_ERROR_TYPE_DEBUG,
1428        "UDP received %u-byte message from `%s' type %i\n", (unsigned int) size,
1429        GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs (msg->type));
1430
1431   if (size != ntohs (msg->size))
1432   {
1433     GNUNET_break_op (0);
1434     return;
1435   }
1436
1437   switch (ntohs (msg->type))
1438   {
1439   case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON:
1440     udp_broadcast_receive (plugin, &buf, size, addr, fromlen);
1441     return;
1442
1443   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
1444     read_process_msg (plugin, msg, addr, fromlen);
1445     return;
1446
1447   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
1448     read_process_ack (plugin, msg, addr, fromlen);;
1449     return;
1450
1451   case GNUNET_MESSAGE_TYPE_FRAGMENT:
1452     read_process_fragment (plugin, msg, addr, fromlen);
1453     return;
1454
1455   default:
1456     GNUNET_break_op (0);
1457     return;
1458   }
1459 }
1460
1461 size_t
1462 udp_select_send (struct Plugin *plugin)
1463 {
1464   ssize_t sent;
1465   size_t slen;
1466   struct GNUNET_TIME_Absolute max;
1467   struct GNUNET_TIME_Absolute ;
1468
1469   struct UDPMessageWrapper *udpw = plugin->msg_head;
1470   const struct sockaddr * sa = udpw->session->sock_addr;
1471
1472   max = GNUNET_TIME_absolute_max(udpw->timeout, GNUNET_TIME_absolute_get());
1473
1474   while (udpw != NULL)
1475   {
1476     if (max.abs_value != udpw->timeout.abs_value)
1477     {
1478       /* Message timed out */
1479
1480       if (udpw->cont != NULL)
1481         udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
1482       if (udpw->frag_ctx != NULL)
1483       {
1484 #if DEBUG_UDP
1485         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fragmented message for peer `%s' with size %u timed out\n",
1486             GNUNET_i2s(&udpw->session->target), udpw->frag_ctx->bytes_to_send);
1487 #endif
1488         udpw->session->last_expected_delay = GNUNET_FRAGMENT_context_destroy(udpw->frag_ctx->frag);
1489         GNUNET_free (udpw->frag_ctx);
1490         udpw->session->frag_ctx = NULL;
1491       }
1492       else
1493       {
1494 #if DEBUG_UDP
1495         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' with size %u timed out\n",
1496             GNUNET_i2s(&udpw->session->target), udpw->msg_size);
1497 #endif
1498       }
1499
1500       GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1501       GNUNET_free (udpw);
1502       udpw = plugin->msg_head;
1503     }
1504     else
1505     {
1506       struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_remaining (udpw->session->flow_delay_from_other_peer);
1507       if (delta.rel_value == 0)
1508       {
1509         /* this message is not delayed */
1510         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is not delayed \n",
1511             GNUNET_i2s(&udpw->session->target), udpw->msg_size);
1512         break;
1513       }
1514       else
1515       {
1516         /* this message is delayed, try next */
1517         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is delayed for %llu \n",
1518             GNUNET_i2s(&udpw->session->target), udpw->msg_size,
1519             delta);
1520         udpw = udpw->next;
1521       }
1522     }
1523
1524   }
1525
1526   if (udpw == NULL)
1527   {
1528     /* No message left */
1529     return 0;
1530   }
1531
1532   switch (sa->sa_family)
1533   {
1534   case AF_INET:
1535     if (NULL == plugin->sockv4)
1536       return 0;
1537     sent =
1538         GNUNET_NETWORK_socket_sendto (plugin->sockv4, udpw->udp, udpw->msg_size,
1539                                       sa, slen = sizeof (struct sockaddr_in));
1540     break;
1541   case AF_INET6:
1542     if (NULL == plugin->sockv6)
1543       return 0;
1544     sent =
1545         GNUNET_NETWORK_socket_sendto (plugin->sockv6, udpw->udp, udpw->msg_size,
1546                                       sa, slen = sizeof (struct sockaddr_in6));
1547     break;
1548   default:
1549     GNUNET_break (0);
1550     return 0;
1551   }
1552   if (GNUNET_SYSERR == sent)
1553   {
1554     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
1555     LOG (GNUNET_ERROR_TYPE_DEBUG,
1556          "UDP transmitted %u-byte message to %s (%d: %s)\n",
1557          (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
1558          (sent < 0) ? STRERROR (errno) : "ok");
1559     if (udpw->cont != NULL)
1560       udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
1561   }
1562   LOG (GNUNET_ERROR_TYPE_DEBUG,
1563        "UDP transmitted %u-byte message to %s (%d: %s)\n",
1564        (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
1565        (sent < 0) ? STRERROR (errno) : "ok");
1566
1567   /* This was just a message fragment */
1568   if (udpw->frag_ctx != NULL)
1569   {
1570     GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);
1571   }
1572   /* This was a complete message*/
1573   else
1574   {
1575     if (udpw->cont != NULL)
1576       udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_OK);
1577   }
1578
1579   GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1580   GNUNET_free (udpw);
1581
1582   return sent;
1583 }
1584
1585 /**
1586  * We have been notified that our readset has something to read.  We don't
1587  * know which socket needs to be read, so we have to check each one
1588  * Then reschedule this function to be called again once more is available.
1589  *
1590  * @param cls the plugin handle
1591  * @param tc the scheduling context (for rescheduling this function again)
1592  */
1593 static void
1594 udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1595 {
1596   struct Plugin *plugin = cls;
1597
1598   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1599   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1600     return;
1601
1602   if ((tc->reason & GNUNET_SCHEDULER_REASON_READ_READY) != 0)
1603   {
1604     if ((NULL != plugin->sockv4) &&
1605       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
1606         udp_select_read (plugin, plugin->sockv4);
1607     if ((NULL != plugin->sockv6) &&
1608       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
1609         udp_select_read (plugin, plugin->sockv6);
1610   }
1611
1612   if ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0)
1613   {
1614     if (plugin->msg_head != NULL)
1615       udp_select_send (plugin);
1616   }
1617
1618   plugin->select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1619                                    GNUNET_SCHEDULER_NO_TASK,
1620                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1621                                    plugin->ws, &udp_plugin_select, plugin);
1622
1623 }
1624
1625
1626 static int
1627 setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct sockaddr_in *serverAddrv4)
1628 {
1629   int tries;
1630   int sockets_created = 0;
1631   struct sockaddr *serverAddr;
1632   struct sockaddr *addrs[2];
1633   socklen_t addrlens[2];
1634   socklen_t addrlen;
1635
1636   /* Create IPv6 socket */
1637   if (plugin->enable_ipv6 == GNUNET_YES)
1638   {
1639     plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1640     if (NULL == plugin->sockv6)
1641     {
1642       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Disabling IPv6 since it is not supported on this system!");
1643       plugin->enable_ipv6 = GNUNET_NO;
1644     }
1645     else
1646     {
1647 #if HAVE_SOCKADDR_IN_SIN_LEN
1648       serverAddrv6->sin6_len = sizeof (serverAddrv6);
1649 #endif
1650       serverAddrv6->sin6_family = AF_INET6;
1651       serverAddrv6->sin6_addr = in6addr_any;
1652       serverAddrv6->sin6_port = htons (plugin->port);
1653       addrlen = sizeof (struct sockaddr_in6);
1654       serverAddr = (struct sockaddr *) serverAddrv6;
1655 #if DEBUG_UDP
1656       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
1657            ntohs (serverAddrv6->sin6_port));
1658 #endif
1659       tries = 0;
1660       while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
1661              GNUNET_OK)
1662       {
1663         serverAddrv6->sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);        /* Find a good, non-root port */
1664 #if DEBUG_UDP
1665         LOG (GNUNET_ERROR_TYPE_DEBUG,
1666              "IPv6 Binding failed, trying new port %d\n",
1667              ntohs (serverAddrv6->sin6_port));
1668 #endif
1669         tries++;
1670         if (tries > 10)
1671         {
1672           GNUNET_NETWORK_socket_close (plugin->sockv6);
1673           plugin->sockv6 = NULL;
1674           break;
1675         }
1676       }
1677       if (plugin->sockv6 != NULL)
1678       {
1679 #if DEBUG_UDP
1680         LOG (GNUNET_ERROR_TYPE_DEBUG,
1681              "IPv6 socket created on port %d\n",
1682              ntohs (serverAddrv6->sin6_port));
1683 #endif
1684         addrs[sockets_created] = (struct sockaddr *) serverAddrv6;
1685         addrlens[sockets_created] = sizeof (struct sockaddr_in6);
1686         sockets_created++;
1687       }
1688     }
1689   }
1690
1691   /* Create IPv4 socket */
1692   plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1693   if (NULL == plugin->sockv4)
1694   {
1695     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1696   }
1697   else
1698   {
1699 #if HAVE_SOCKADDR_IN_SIN_LEN
1700     serverAddrv4->sin_len = sizeof (serverAddrv4);
1701 #endif
1702     serverAddrv4->sin_family = AF_INET;
1703     serverAddrv4->sin_addr.s_addr = INADDR_ANY;
1704     serverAddrv4->sin_port = htons (plugin->port);
1705     addrlen = sizeof (struct sockaddr_in);
1706     serverAddr = (struct sockaddr *) serverAddrv4;
1707
1708 #if DEBUG_UDP
1709     LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
1710          ntohs (serverAddrv4->sin_port));
1711 #endif
1712     tries = 0;
1713     while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
1714            GNUNET_OK)
1715     {
1716       serverAddrv4->sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);   /* Find a good, non-root port */
1717 #if DEBUG_UDP
1718       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Binding failed, trying new port %d\n",
1719            ntohs (serverAddrv4->sin_port));
1720 #endif
1721       tries++;
1722       if (tries > 10)
1723       {
1724         GNUNET_NETWORK_socket_close (plugin->sockv4);
1725         plugin->sockv4 = NULL;
1726         break;
1727       }
1728     }
1729     if (plugin->sockv4 != NULL)
1730     {
1731       addrs[sockets_created] = (struct sockaddr *) serverAddrv4;
1732       addrlens[sockets_created] = sizeof (struct sockaddr_in);
1733       sockets_created++;
1734     }
1735   }
1736
1737   /* Create file descriptors */
1738   plugin->rs = GNUNET_NETWORK_fdset_create ();
1739   plugin->ws = GNUNET_NETWORK_fdset_create ();
1740   GNUNET_NETWORK_fdset_zero (plugin->rs);
1741   GNUNET_NETWORK_fdset_zero (plugin->ws);
1742   if (NULL != plugin->sockv4)
1743   {
1744     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4);
1745     GNUNET_NETWORK_fdset_set (plugin->ws, plugin->sockv4);
1746   }
1747   if (NULL != plugin->sockv6)
1748   {
1749     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6);
1750     GNUNET_NETWORK_fdset_set (plugin->ws, plugin->sockv6);
1751   }
1752
1753   if (sockets_created == 0)
1754     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
1755
1756   plugin->select_task =
1757       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1758                                    GNUNET_SCHEDULER_NO_TASK,
1759                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1760                                    plugin->ws, &udp_plugin_select, plugin);
1761
1762   plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
1763                            GNUNET_NO, plugin->port,
1764                            sockets_created,
1765                            (const struct sockaddr **) addrs, addrlens,
1766                            &udp_nat_port_map_callback, NULL, plugin);
1767
1768   return sockets_created;
1769 }
1770
1771
1772 /**
1773  * The exported method. Makes the core api available via a global and
1774  * returns the udp transport API.
1775  *
1776  * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1777  * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1778  */
1779 void *
1780 libgnunet_plugin_transport_udp_init (void *cls)
1781 {
1782   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1783   struct GNUNET_TRANSPORT_PluginFunctions *api;
1784   struct Plugin *plugin;
1785
1786   unsigned long long port;
1787   unsigned long long aport;
1788   unsigned long long broadcast;
1789   unsigned long long udp_max_bps;
1790   unsigned long long enable_v6;
1791   char * bind4_address;
1792   char * bind6_address;
1793   struct GNUNET_TIME_Relative interval;
1794
1795   struct sockaddr_in serverAddrv4;
1796   struct sockaddr_in6 serverAddrv6;
1797
1798   int res;
1799
1800   /* Get port number */
1801   if (GNUNET_OK !=
1802       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
1803                                              &port))
1804     port = 2086;
1805   if (GNUNET_OK !=
1806       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1807                                              "ADVERTISED_PORT", &aport))
1808     aport = port;
1809   if (port > 65535)
1810   {
1811     LOG (GNUNET_ERROR_TYPE_WARNING,
1812          _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port,
1813          65535);
1814     return NULL;
1815   }
1816
1817   /* Protocols */
1818   if ((GNUNET_YES ==
1819        GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "nat",
1820                                              "DISABLEV6")))
1821   {
1822     enable_v6 = GNUNET_NO;
1823   }
1824   else
1825     enable_v6 = GNUNET_YES;
1826
1827
1828   /* Addresses */
1829   memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1830   memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1831
1832   if (GNUNET_YES ==
1833       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1834                                              "BINDTO", &bind4_address))
1835   {
1836     LOG (GNUNET_ERROR_TYPE_DEBUG,
1837          "Binding udp plugin to specific address: `%s'\n",
1838          bind4_address);
1839     if (1 != inet_pton (AF_INET, bind4_address, &serverAddrv4.sin_addr))
1840     {
1841       GNUNET_free (bind4_address);
1842       return NULL;
1843     }
1844   }
1845
1846   if (GNUNET_YES ==
1847       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1848                                              "BINDTO6", &bind6_address))
1849   {
1850     LOG (GNUNET_ERROR_TYPE_DEBUG,
1851          "Binding udp plugin to specific address: `%s'\n",
1852          bind6_address);
1853     if (1 !=
1854         inet_pton (AF_INET6, bind6_address, &serverAddrv6.sin6_addr))
1855     {
1856       LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
1857            bind6_address);
1858       GNUNET_free_non_null (bind4_address);
1859       GNUNET_free (bind6_address);
1860       return NULL;
1861     }
1862   }
1863
1864
1865   /* Enable neighbour discovery */
1866   broadcast = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
1867                                             "BROADCAST");
1868   if (broadcast == GNUNET_SYSERR)
1869     broadcast = GNUNET_NO;
1870
1871   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
1872                                            "BROADCAST_INTERVAL", &interval))
1873   {
1874     interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1875   }
1876
1877   /* Maximum datarate */
1878   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1879                                              "MAX_BPS", &udp_max_bps))
1880   {
1881     udp_max_bps = 1024 * 1024 * 50;     /* 50 MB/s == infinity for practical purposes */
1882   }
1883
1884   plugin = GNUNET_malloc (sizeof (struct Plugin));
1885   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1886
1887   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
1888                                  GNUNET_BANDWIDTH_value_init ((uint32_t)udp_max_bps), 30);
1889
1890
1891   plugin->sessions = GNUNET_CONTAINER_multihashmap_create (10);
1892   plugin->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1893   plugin->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
1894   plugin->port = port;
1895   plugin->aport = aport;
1896   plugin->broadcast_interval = interval;
1897   plugin->enable_ipv6 = enable_v6;
1898   plugin->env = env;
1899
1900   api->cls = plugin;
1901   api->send = NULL;
1902   api->disconnect = &udp_disconnect;
1903   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
1904   api->address_to_string = &udp_address_to_string;
1905   api->check_address = &udp_plugin_check_address;
1906   api->get_session = &udp_plugin_get_session;
1907   api->send = &udp_plugin_send;
1908
1909   LOG (GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n");
1910   res = setup_sockets (plugin, &serverAddrv6, &serverAddrv4);
1911   if ((res == 0) || ((plugin->sockv4 == NULL) && (plugin->sockv6 == NULL)))
1912   {
1913     LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create network sockets, plugin failed\n");
1914     GNUNET_free (plugin);
1915     GNUNET_free (api);
1916     return NULL;
1917   }
1918
1919   LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting broadcasting\n");
1920   if (broadcast == GNUNET_YES)
1921     setup_broadcast (plugin, &serverAddrv6, &serverAddrv4);
1922
1923
1924   GNUNET_free_non_null (bind4_address);
1925   GNUNET_free_non_null (bind6_address);
1926   return api;
1927 }
1928
1929 int heap_cleanup_iterator (void *cls,
1930                           struct GNUNET_CONTAINER_HeapNode *
1931                           node, void *element,
1932                           GNUNET_CONTAINER_HeapCostType
1933                           cost)
1934 {
1935   struct DefragContext * d_ctx = element;
1936
1937   GNUNET_CONTAINER_heap_remove_node (node);
1938   GNUNET_DEFRAGMENT_context_destroy(d_ctx->defrag);
1939   GNUNET_free (d_ctx);
1940
1941   return GNUNET_YES;
1942 }
1943
1944
1945 /**
1946  * The exported method. Makes the core api available via a global and
1947  * returns the udp transport API.
1948  *
1949  * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1950  * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1951  */
1952 void *
1953 libgnunet_plugin_transport_udp_done (void *cls)
1954 {
1955   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1956   struct Plugin *plugin = api->cls;
1957   stop_broadcast (plugin);
1958
1959   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
1960   {
1961     GNUNET_SCHEDULER_cancel (plugin->select_task);
1962     plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1963   }
1964
1965   /* Closing sockets */
1966   if (plugin->sockv4 != NULL)
1967   {
1968     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
1969     plugin->sockv4 = NULL;
1970   }
1971   if (plugin->sockv6 != NULL)
1972   {
1973     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
1974     plugin->sockv6 = NULL;
1975   }
1976   GNUNET_NETWORK_fdset_destroy (plugin->rs);
1977   GNUNET_NETWORK_fdset_destroy (plugin->ws);
1978   GNUNET_NAT_unregister (plugin->nat);
1979
1980   if (plugin->defrag_ctxs != NULL)
1981   {
1982     GNUNET_CONTAINER_heap_iterate(plugin->defrag_ctxs,
1983         heap_cleanup_iterator, NULL);
1984     GNUNET_CONTAINER_heap_destroy(plugin->defrag_ctxs);
1985     plugin->defrag_ctxs = NULL;
1986   }
1987   if (plugin->mst != NULL)
1988   {
1989     GNUNET_SERVER_mst_destroy(plugin->mst);
1990     plugin->mst = NULL;
1991   }
1992
1993   /* Clean up leftover messages */
1994   struct UDPMessageWrapper *udpw = plugin->msg_head;
1995   while (udpw != NULL)
1996   {
1997     struct UDPMessageWrapper *tmp = udpw->next;
1998     GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, udpw);
1999     if (udpw->cont != NULL)
2000       udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
2001     GNUNET_free (udpw);
2002     udpw = tmp;
2003   }
2004
2005   /* Clean up sessions */
2006 #if DEBUG_UDP
2007   LOG (GNUNET_ERROR_TYPE_DEBUG,
2008        "Cleaning up sessions\n");
2009 #endif
2010   GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
2011   GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
2012
2013   plugin->nat = NULL;
2014   GNUNET_free (plugin);
2015   GNUNET_free (api);
2016   return NULL;
2017 }
2018
2019
2020 /* end of plugin_transport_udp.c */