a74f25700762ed433a880b7fd197750a232b020e
[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 NAT punching
24  *        transport service
25  * @author Christian Grothoff
26  * @author Nathan Evans
27  */
28 #include "platform.h"
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_statistics_service.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_transport_plugin.h"
39 #include "transport.h"
40
41 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
42
43
44 #define DEBUG_UDP GNUNET_EXTRA_LOGGING
45
46 /**
47  * MTU for fragmentation subsystem.  Should be conservative since
48  * all communicating peers MUST work with this MTU.
49  */
50 #define UDP_MTU 1400
51
52 /**
53  * Number of messages we can defragment in parallel.  We only really
54  * defragment 1 message at a time, but if messages get re-ordered, we
55  * may want to keep knowledge about the previous message to avoid
56  * discarding the current message in favor of a single fragment of a
57  * previous message.  3 should be good since we don't expect massive
58  * message reorderings with UDP.
59  */
60 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
61
62 /**
63  * We keep a defragmentation queue per sender address.  How many
64  * sender addresses do we support at the same time? Memory consumption
65  * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this
66  * value. (So 128 corresponds to 12 MB and should suffice for
67  * connecting to roughly 128 peers via UDP).
68  */
69 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
70
71
72 /**
73  * UDP Message-Packet header (after defragmentation).
74  */
75 struct UDPMessage
76 {
77   /**
78    * Message header.
79    */
80   struct GNUNET_MessageHeader header;
81
82   /**
83    * Always zero for now.
84    */
85   uint32_t reserved;
86
87   /**
88    * What is the identity of the sender
89    */
90   struct GNUNET_PeerIdentity sender;
91
92 };
93
94
95 /**
96  * Network format for IPv4 addresses.
97  */
98 struct IPv4UdpAddress
99 {
100   /**
101    * IPv4 address, in network byte order.
102    */
103   uint32_t ipv4_addr GNUNET_PACKED;
104
105   /**
106    * Port number, in network byte order.
107    */
108   uint16_t u4_port GNUNET_PACKED;
109 };
110
111
112 /**
113  * Network format for IPv6 addresses.
114  */
115 struct IPv6UdpAddress
116 {
117
118   /**
119    * IPv6 address.
120    */
121   struct in6_addr ipv6_addr GNUNET_PACKED;
122
123   /**
124    * Port number, in network byte order.
125    */
126   uint16_t u6_port GNUNET_PACKED;
127 };
128
129
130 /* Forward definition */
131 struct Plugin;
132
133
134 /**
135  * Session with another peer.  FIXME: why not make this into
136  * a regular 'struct Session' and pass it around!?
137  */
138 struct PeerSession
139 {
140
141   /**
142    * Which peer is this session for?
143    */
144   struct GNUNET_PeerIdentity target;
145
146   /**
147    * Pointer to the global plugin struct.
148    */
149   struct Plugin *plugin;
150
151   /**
152    * Address of the other peer
153    */
154   const struct sockaddr *sock_addr;
155
156   size_t addrlen;
157
158   /**
159    * Function to call upon completion of the transmission.
160    */
161   GNUNET_TRANSPORT_TransmitContinuation cont;
162
163   /**
164    * Closure for 'cont'.
165    */
166   void *cont_cls;
167
168   /**
169    * Current outgoing message to this peer.
170    */
171   struct GNUNET_FRAGMENT_Context *frag;
172
173 };
174
175
176 /**
177  * Data structure to track defragmentation contexts based
178  * on the source of the UDP traffic.
179  */
180 struct ReceiveContext
181 {
182
183   /**
184    * Defragmentation context.
185    */
186   struct GNUNET_DEFRAGMENT_Context *defrag;
187
188   /**
189    * Source address this receive context is for (allocated at the
190    * end of the struct).
191    */
192   const struct sockaddr *src_addr;
193
194   /**
195    * Reference to master plugin struct.
196    */
197   struct Plugin *plugin;
198
199   /**
200    * Node in the defrag heap.
201    */
202   struct GNUNET_CONTAINER_HeapNode *hnode;
203
204   /**
205    * Length of 'src_addr'
206    */
207   size_t addr_len;
208
209 };
210
211
212 /**
213  * Encapsulation of all of the state of the plugin.
214  */
215 struct Plugin
216 {
217
218   /**
219    * Our environment.
220    */
221   struct GNUNET_TRANSPORT_PluginEnvironment *env;
222
223   /**
224    * Session of peers with whom we are currently connected,
225    * map of peer identity to 'struct PeerSession'.
226    */
227   struct GNUNET_CONTAINER_MultiHashMap *sessions;
228
229   /**
230    * Session of peers with whom we are currently connected,
231    * map of peer identity to 'struct PeerSession'.
232    */
233   struct GNUNET_CONTAINER_MultiHashMap *inbound_sessions;
234
235   /**
236    * Heap with all of our defragmentation activities.
237    */
238   struct GNUNET_CONTAINER_Heap *defrags;
239
240   /**
241    * ID of select task
242    */
243   GNUNET_SCHEDULER_TaskIdentifier select_task;
244
245   /**
246    * Tokenizer for inbound messages.
247    */
248   struct GNUNET_SERVER_MessageStreamTokenizer *mst;
249
250   /**
251    * Bandwidth tracker to limit global UDP traffic.
252    */
253   struct GNUNET_BANDWIDTH_Tracker tracker;
254
255   /**
256    * Address we were told to bind to exclusively (IPv4).
257    */
258   char *bind4_address;
259
260   /**
261    * Address we were told to bind to exclusively (IPv6).
262    */
263   char *bind6_address;
264
265   /**
266    * Handle to NAT traversal support.
267    */
268   struct GNUNET_NAT_Handle *nat;
269
270   /**
271    * FD Read set
272    */
273   struct GNUNET_NETWORK_FDSet *rs;
274
275   /**
276    * The read socket for IPv4
277    */
278   struct GNUNET_NETWORK_Handle *sockv4;
279
280   /**
281    * The read socket for IPv6
282    */
283   struct GNUNET_NETWORK_Handle *sockv6;
284
285   /**
286    * expected delay for ACKs
287    */
288   struct GNUNET_TIME_Relative last_expected_delay;
289
290   /**
291    * Port we listen on.
292    */
293   uint16_t port;
294
295   /**
296    * Port we advertise on.
297    */
298   uint16_t aport;
299
300 };
301
302 struct PeerSessionIteratorContext
303 {
304   struct PeerSession * result;
305   const void * addr;
306   size_t addrlen;
307 };
308
309
310 /**
311  * Lookup the session for the given peer.
312  *
313  * @param plugin the plugin
314  * @param peer peer's identity
315  * @return NULL if we have no session
316  */
317 struct PeerSession *
318 find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
319 {
320   return GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
321                                             &peer->hashPubKey);
322 }
323
324 int inbound_session_iterator (void *cls,
325                              const GNUNET_HashCode * key,
326                              void *value)
327 {
328   struct PeerSessionIteratorContext *psc = cls;
329   struct PeerSession *s = value;
330   if (s->addrlen == psc->addrlen)
331   {
332     if (0 == memcmp (&s[1], psc->addr, s->addrlen))
333       psc->result = s;
334   }
335   if (psc->result != NULL)
336     return GNUNET_NO;
337   else
338     return GNUNET_YES;
339 };
340
341 /**
342  * Lookup the session for the given peer.
343  *
344  * @param plugin the plugin
345  * @param peer peer's identity
346  * @return NULL if we have no session
347  */
348 struct PeerSession *
349 find_inbound_session (struct Plugin *plugin,
350                       const struct GNUNET_PeerIdentity *peer,
351                       const void * addr, size_t addrlen)
352 {
353   struct PeerSessionIteratorContext psc;
354   psc.result = NULL;
355   psc.addrlen = addrlen;
356   psc.addr = addr;
357
358   GNUNET_CONTAINER_multihashmap_get_multiple(plugin->inbound_sessions, &peer->hashPubKey, &inbound_session_iterator, &psc);
359   return psc.result;
360 }
361
362
363 /**
364  * Disconnect from a remote node.  Clean up session if we have one for this peer
365  *
366  * @param cls closure for this call (should be handle to Plugin)
367  * @param target the peeridentity of the peer to disconnect
368  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
369  */
370 static void
371 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
372 {
373   struct Plugin *plugin = cls;
374   struct PeerSession *session;
375
376   session = find_session (plugin, target);
377   if (NULL == session)
378     return;
379   GNUNET_assert (GNUNET_OK ==
380                  GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
381                                                        &target->hashPubKey,
382                                                        session));
383   plugin->last_expected_delay = GNUNET_FRAGMENT_context_destroy (session->frag);
384   if (session->cont != NULL)
385     session->cont (session->cont_cls, target, GNUNET_SYSERR);
386   GNUNET_free (session);
387 }
388
389
390 /**
391  * Actually send out the message.
392  *
393  * @param plugin the plugin
394  * @param sa the address to send the message to
395  * @param msg message to transmit
396  * @return the number of bytes written
397  */
398 static ssize_t
399 udp_send (struct Plugin *plugin, const struct sockaddr *sa,
400           const struct GNUNET_MessageHeader *msg)
401 {
402   ssize_t sent;
403   size_t slen;
404
405   switch (sa->sa_family)
406   {
407   case AF_INET:
408     if (NULL == plugin->sockv4)
409       return 0;
410     sent =
411         GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, ntohs (msg->size),
412                                       sa, slen = sizeof (struct sockaddr_in));
413     break;
414   case AF_INET6:
415     if (NULL == plugin->sockv6)
416       return 0;
417     sent =
418         GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, ntohs (msg->size),
419                                       sa, slen = sizeof (struct sockaddr_in6));
420     break;
421   default:
422     GNUNET_break (0);
423     return 0;
424   }
425   if (GNUNET_SYSERR == sent)
426     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
427   LOG (GNUNET_ERROR_TYPE_ERROR,
428               "UDP transmited %u-byte message to %s (%d: %s)\n",
429               (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen),
430               (int) sent, (sent < 0) ? STRERROR (errno) : "ok");
431   return sent;
432 }
433
434
435 /**
436  * Function that is called with messages created by the fragmentation
437  * module.  In the case of the 'proc' callback of the
438  * GNUNET_FRAGMENT_context_create function, this function must
439  * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
440  *
441  * @param cls closure, the 'struct PeerSession'
442  * @param msg the message that was created
443  */
444 static void
445 send_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
446 {
447   struct PeerSession *session = cls;
448
449   udp_send (session->plugin, session->sock_addr, msg);
450   GNUNET_FRAGMENT_context_transmission_done (session->frag);
451 }
452
453 static struct PeerSession *
454 create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
455     const void *addr, size_t addrlen,
456     GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
457 {
458   struct PeerSession * peer_session;
459   const struct IPv4UdpAddress *t4;
460   const struct IPv6UdpAddress *t6;
461   struct sockaddr_in *v4;
462   struct sockaddr_in6 *v6;
463   size_t len;
464
465   switch (addrlen)
466   {
467   case sizeof (struct IPv4UdpAddress):
468     if (NULL == plugin->sockv4)
469     {
470       return NULL;
471     }
472     t4 = addr;
473     peer_session =
474         GNUNET_malloc (sizeof (struct PeerSession) +
475                        sizeof (struct sockaddr_in));
476     len = sizeof (struct sockaddr_in);
477     v4 = (struct sockaddr_in *) &peer_session[1];
478     v4->sin_family = AF_INET;
479 #if HAVE_SOCKADDR_IN_SIN_LEN
480     v4->sin_len = sizeof (struct sockaddr_in);
481 #endif
482     v4->sin_port = t4->u4_port;
483     v4->sin_addr.s_addr = t4->ipv4_addr;
484     break;
485   case sizeof (struct IPv6UdpAddress):
486     if (NULL == plugin->sockv6)
487     {
488       return NULL;
489     }
490     t6 = addr;
491     peer_session =
492         GNUNET_malloc (sizeof (struct PeerSession) +
493                        sizeof (struct sockaddr_in6));
494     len = sizeof (struct sockaddr_in6);
495     v6 = (struct sockaddr_in6 *) &peer_session[1];
496     v6->sin6_family = AF_INET6;
497 #if HAVE_SOCKADDR_IN_SIN_LEN
498     v6->sin6_len = sizeof (struct sockaddr_in6);
499 #endif
500     v6->sin6_port = t6->u6_port;
501     v6->sin6_addr = t6->ipv6_addr;
502     break;
503   default:
504     /* Must have a valid address to send to */
505     GNUNET_break_op (0);
506     return NULL;
507   }
508
509   peer_session->addrlen = len;
510   peer_session->target = *target;
511   peer_session->plugin = plugin;
512   peer_session->sock_addr = (const struct sockaddr *) &peer_session[1];
513   peer_session->cont = cont;
514   peer_session->cont_cls = cont_cls;
515
516   return peer_session;
517 }
518
519 static const char *
520 udp_address_to_string (void *cls, const void *addr, size_t addrlen);
521
522 /**
523  * Function that can be used by the transport service to transmit
524  * a message using the plugin.
525  *
526  * @param cls closure
527  * @param target who should receive this message (ignored by UDP)
528  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
529  * @param msgbuf_size the size of the msgbuf to send
530  * @param priority how important is the message (ignored by UDP)
531  * @param timeout when should we time out (give up) if we can not transmit?
532  * @param session identifier used for this session (NULL for UDP)
533  * @param addr the addr to send the message to
534  * @param addrlen the len of addr
535  * @param force_address not used, we had better have an address to send to
536  *        because we are stateless!!
537  * @param cont continuation to call once the message has
538  *        been transmitted (or if the transport is ready
539  *        for the next transmission call; or if the
540  *        peer disconnected...)
541  * @param cont_cls closure for cont
542  *
543  * @return the number of bytes written (may return 0 and the message can
544  *         still be transmitted later!)
545  */
546 static ssize_t
547 udp_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
548                  const char *msgbuf, size_t msgbuf_size, unsigned int priority,
549                  struct GNUNET_TIME_Relative timeout, struct Session *session,
550                  const void *addr, size_t addrlen, int force_address,
551                  GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
552 {
553   struct Plugin *plugin = cls;
554   struct PeerSession *peer_session;
555   struct PeerSession *inbound_session;
556   size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
557   char mbuf[mlen];
558   struct UDPMessage *udp;
559
560   if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
561   {
562     GNUNET_break (0);
563     return GNUNET_SYSERR;
564   }
565
566   if (force_address == GNUNET_SYSERR)
567     return GNUNET_SYSERR;
568
569   LOG (GNUNET_ERROR_TYPE_DEBUG,
570               "UDP transmits %u-byte message to `%s' using address `%s' session 0x%X\n",
571               msgbuf_size, GNUNET_i2s (target), udp_address_to_string (NULL, addr, addrlen), session);
572
573   if (session != NULL)
574   {
575     inbound_session = (struct PeerSession *) session;
576     GNUNET_assert (0 == memcmp (&inbound_session->target, target, sizeof (struct GNUNET_PeerIdentity)));
577   }
578
579   peer_session = create_session (plugin, target, addr, addrlen, cont, cont_cls);
580   if (peer_session == NULL)
581   {
582     if (cont != NULL)
583       cont (cont_cls, target, GNUNET_SYSERR);
584   }
585
586   /* Message */
587   udp = (struct UDPMessage *) mbuf;
588   udp->header.size = htons (mlen);
589   udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
590   udp->reserved = htonl (0);
591   udp->sender = *plugin->env->my_identity;
592   memcpy (&udp[1], msgbuf, msgbuf_size);
593
594   if (mlen <= UDP_MTU)
595   {
596     mlen = udp_send (plugin, peer_session->sock_addr, &udp->header);
597     if (cont != NULL)
598       cont (cont_cls, target, (mlen > 0) ? GNUNET_OK : GNUNET_SYSERR);
599     GNUNET_free_non_null (peer_session);
600   }
601   else
602   {
603     GNUNET_assert (GNUNET_OK ==
604                    GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
605                                                       &target->hashPubKey,
606                                                       peer_session,
607                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
608     peer_session->frag =
609         GNUNET_FRAGMENT_context_create (plugin->env->stats, UDP_MTU,
610                                         &plugin->tracker,
611                                         plugin->last_expected_delay,
612                                         &udp->header, &send_fragment,
613                                         peer_session);
614   }
615   return mlen;
616 }
617
618
619 /**
620  * Closure for 'process_inbound_tokenized_messages'
621  */
622 struct SourceInformation
623 {
624   /**
625    * Sender identity.
626    */
627   struct GNUNET_PeerIdentity sender;
628
629   /**
630    * Source address.
631    */
632   const void *arg;
633
634   /**
635    * Number of bytes in source address.
636    */
637   size_t args;
638
639   struct PeerSession * session;
640 };
641
642
643 /**
644  * Message tokenizer has broken up an incomming message. Pass it on
645  * to the service.
646  *
647  * @param cls the 'struct Plugin'
648  * @param client the 'struct SourceInformation'
649  * @param hdr the actual message
650  */
651 static void
652 process_inbound_tokenized_messages (void *cls, void *client,
653                                     const struct GNUNET_MessageHeader *hdr)
654 {
655   struct Plugin *plugin = cls;
656   struct SourceInformation *si = client;
657   struct GNUNET_TRANSPORT_ATS_Information distance[2];
658
659   /* setup ATS */
660   distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
661   distance[0].value = htonl (1);
662   distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
663   distance[1].value = htonl (0);
664
665   LOG (GNUNET_ERROR_TYPE_DEBUG,
666                    "Giving Session %X %s  to transport\n", (struct Session *) si->session, GNUNET_i2s(&si->session->target));
667   plugin->env->receive (plugin->env->cls, &si->sender, hdr, distance, 2, (struct Session *) si->session,
668                         si->arg, si->args);
669 }
670
671
672 /**
673  * We've received a UDP Message.  Process it (pass contents to main service).
674  *
675  * @param plugin plugin context
676  * @param msg the message
677  * @param sender_addr sender address
678  * @param sender_addr_len number of bytes in sender_addr
679  */
680 static void
681 process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
682                      const struct sockaddr *sender_addr,
683                      socklen_t sender_addr_len)
684 {
685   struct SourceInformation si;
686   struct IPv4UdpAddress u4;
687   struct IPv6UdpAddress u6;
688   const void *arg;
689   size_t args;
690
691   if (0 != ntohl (msg->reserved))
692   {
693     GNUNET_break_op (0);
694     return;
695   }
696   if (ntohs (msg->header.size) <
697       sizeof (struct GNUNET_MessageHeader) + sizeof (struct UDPMessage))
698   {
699     GNUNET_break_op (0);
700     return;
701   }
702
703   /* convert address */
704   switch (sender_addr->sa_family)
705   {
706   case AF_INET:
707     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in));
708     u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr;
709     u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port;
710     arg = &u4;
711     args = sizeof (u4);
712     break;
713   case AF_INET6:
714     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in6));
715     u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr;
716     u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port;
717     arg = &u6;
718     args = sizeof (u6);
719     break;
720   default:
721     GNUNET_break (0);
722     return;
723   }
724 #if DEBUG_UDP
725   LOG (GNUNET_ERROR_TYPE_DEBUG,
726                    "Received message with %u bytes from peer `%s' at `%s'\n",
727                    (unsigned int) ntohs (msg->header.size),
728                    GNUNET_i2s (&msg->sender), GNUNET_a2s (sender_addr,
729                                                           sender_addr_len));
730 #endif
731
732   /* create a session for inbound connections */
733   const struct UDPMessage * udp_msg = (const struct UDPMessage *) msg;
734   LOG (GNUNET_ERROR_TYPE_DEBUG,
735               "Lookup inbound UDP sessions for peer `%s' address `%s'\n",
736               GNUNET_i2s (&udp_msg->sender),
737               udp_address_to_string(NULL, arg, args));
738
739   struct PeerSession * s = NULL;
740   s = find_inbound_session (plugin, &udp_msg->sender, sender_addr, sender_addr_len);
741
742   if (s != NULL)
743   {
744     LOG (GNUNET_ERROR_TYPE_DEBUG,
745                 "Found existing inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
746                 s,
747                 GNUNET_i2s (&s->target),
748                 udp_address_to_string(NULL, arg, args));
749   }
750   else
751   {
752     s = create_session (plugin, &udp_msg->sender, arg, args, NULL, NULL);
753     LOG (GNUNET_ERROR_TYPE_DEBUG,
754                 "Creating inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
755                 s,
756                 GNUNET_i2s (&s->target),
757                 udp_address_to_string(NULL, arg, args));
758
759     GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (plugin->inbound_sessions,
760                                                       &s->target.hashPubKey,
761                                                       s,
762                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
763   }
764
765   /* iterate over all embedded messages */
766   si.sender = msg->sender;
767   si.arg = arg;
768   si.args = args;
769   si.session = s;
770   GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
771                              ntohs (msg->header.size) -
772                              sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
773 }
774
775
776 /**
777  * Process a defragmented message.
778  *
779  * @param cls the 'struct ReceiveContext'
780  * @param msg the message
781  */
782 static void
783 fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
784 {
785   struct ReceiveContext *rc = cls;
786
787   if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
788   {
789     GNUNET_break (0);
790     return;
791   }
792   if (ntohs (msg->size) < sizeof (struct UDPMessage))
793   {
794     GNUNET_break (0);
795     return;
796   }
797   process_udp_message (rc->plugin, (const struct UDPMessage *) msg,
798                        rc->src_addr, rc->addr_len);
799 }
800
801
802 /**
803  * Transmit an acknowledgement.
804  *
805  * @param cls the 'struct ReceiveContext'
806  * @param id message ID (unused)
807  * @param msg ack to transmit
808  */
809 static void
810 ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
811 {
812   struct ReceiveContext *rc = cls;
813   size_t msize = sizeof (struct UDPMessage) + ntohs (msg->size);
814   char buf[msize];
815   struct UDPMessage *udp;
816
817 #if DEBUG_UDP
818   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK to `%s'\n",
819                    GNUNET_a2s (rc->src_addr,
820                                (rc->src_addr->sa_family ==
821                                 AF_INET) ? sizeof (struct sockaddr_in) :
822                                sizeof (struct sockaddr_in6)));
823 #endif
824   udp = (struct UDPMessage *) buf;
825   udp->header.size = htons ((uint16_t) msize);
826   udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
827   udp->reserved = htonl (0);
828   udp->sender = *rc->plugin->env->my_identity;
829   memcpy (&udp[1], msg, ntohs (msg->size));
830   (void) udp_send (rc->plugin, rc->src_addr, &udp->header);
831 }
832
833
834 /**
835  * Closure for 'find_receive_context'.
836  */
837 struct FindReceiveContext
838 {
839   /**
840    * Where to store the result.
841    */
842   struct ReceiveContext *rc;
843
844   /**
845    * Address to find.
846    */
847   const struct sockaddr *addr;
848
849   /**
850    * Number of bytes in 'addr'.
851    */
852   socklen_t addr_len;
853 };
854
855
856 /**
857  * Scan the heap for a receive context with the given address.
858  *
859  * @param cls the 'struct FindReceiveContext'
860  * @param node internal node of the heap
861  * @param element value stored at the node (a 'struct ReceiveContext')
862  * @param cost cost associated with the node
863  * @return GNUNET_YES if we should continue to iterate,
864  *         GNUNET_NO if not.
865  */
866 static int
867 find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
868                       void *element, GNUNET_CONTAINER_HeapCostType cost)
869 {
870   struct FindReceiveContext *frc = cls;
871   struct ReceiveContext *e = element;
872
873   if ((frc->addr_len == e->addr_len) &&
874       (0 == memcmp (frc->addr, e->src_addr, frc->addr_len)))
875   {
876     frc->rc = e;
877     return GNUNET_NO;
878   }
879   return GNUNET_YES;
880 }
881
882
883 /**
884  * Read and process a message from the given socket.
885  *
886  * @param plugin the overall plugin
887  * @param rsock socket to read from
888  */
889 static void
890 udp_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
891 {
892   socklen_t fromlen;
893   char addr[32];
894   char buf[65536];
895   ssize_t ret;
896   const struct GNUNET_MessageHeader *msg;
897   const struct GNUNET_MessageHeader *ack;
898   struct PeerSession *peer_session;
899   const struct UDPMessage *udp;
900   struct ReceiveContext *rc;
901   struct GNUNET_TIME_Absolute now;
902   struct FindReceiveContext frc;
903
904   fromlen = sizeof (addr);
905   memset (&addr, 0, sizeof (addr));
906   ret =
907       GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
908                                       (struct sockaddr *) &addr, &fromlen);
909   if (ret < sizeof (struct GNUNET_MessageHeader))
910   {
911     GNUNET_break_op (0);
912     return;
913   }
914 #if DEBUG_UDP
915   LOG (GNUNET_ERROR_TYPE_DEBUG,
916               "UDP received %u-byte message from `%s'\n", (unsigned int) ret,
917               GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
918 #endif
919   msg = (const struct GNUNET_MessageHeader *) buf;
920   if (ret != ntohs (msg->size))
921   {
922     GNUNET_break_op (0);
923     return;
924   }
925   switch (ntohs (msg->type))
926   {
927   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
928     if (ntohs (msg->size) < sizeof (struct UDPMessage))
929     {
930       GNUNET_break_op (0);
931       return;
932     }
933     process_udp_message (plugin, (const struct UDPMessage *) msg,
934                          (const struct sockaddr *) addr, fromlen);
935     return;
936   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
937     if (ntohs (msg->size) <
938         sizeof (struct UDPMessage) + sizeof (struct GNUNET_MessageHeader))
939     {
940       GNUNET_break_op (0);
941       return;
942     }
943     udp = (const struct UDPMessage *) msg;
944     if (ntohl (udp->reserved) != 0)
945     {
946       GNUNET_break_op (0);
947       return;
948     }
949     ack = (const struct GNUNET_MessageHeader *) &udp[1];
950     if (ntohs (ack->size) != ntohs (msg->size) - sizeof (struct UDPMessage))
951     {
952       GNUNET_break_op (0);
953       return;
954     }
955 #if DEBUG_UDP
956     LOG (GNUNET_ERROR_TYPE_DEBUG,
957                 "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
958                 (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp->sender),
959                 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
960 #endif
961
962     peer_session = find_session (plugin, &udp->sender);
963     if (NULL == peer_session)
964     {
965 #if DEBUG_UDP
966       LOG (GNUNET_ERROR_TYPE_DEBUG,
967                   "Session for ACK not found, dropping ACK!\n");
968 #endif
969       return;
970     }
971     if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (peer_session->frag, ack))
972       return;
973     GNUNET_assert (GNUNET_OK ==
974                    GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
975                                                          &udp->
976                                                          sender.hashPubKey,
977                                                          peer_session));
978     plugin->last_expected_delay =
979         GNUNET_FRAGMENT_context_destroy (peer_session->frag);
980     if (peer_session->cont != NULL)
981       peer_session->cont (peer_session->cont_cls, &udp->sender, GNUNET_OK);
982     GNUNET_free (peer_session);
983     return;
984   case GNUNET_MESSAGE_TYPE_FRAGMENT:
985     frc.rc = NULL;
986     frc.addr = (const struct sockaddr *) addr;
987     frc.addr_len = fromlen;
988     GNUNET_CONTAINER_heap_iterate (plugin->defrags, &find_receive_context,
989                                    &frc);
990     now = GNUNET_TIME_absolute_get ();
991     rc = frc.rc;
992     if (rc == NULL)
993     {
994       /* need to create a new RC */
995       rc = GNUNET_malloc (sizeof (struct ReceiveContext) + fromlen);
996       memcpy (&rc[1], addr, fromlen);
997       rc->src_addr = (const struct sockaddr *) &rc[1];
998       rc->addr_len = fromlen;
999       rc->plugin = plugin;
1000       rc->defrag =
1001           GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1002                                             UDP_MAX_MESSAGES_IN_DEFRAG, rc,
1003                                             &fragment_msg_proc, &ack_proc);
1004       rc->hnode =
1005           GNUNET_CONTAINER_heap_insert (plugin->defrags, rc,
1006                                         (GNUNET_CONTAINER_HeapCostType)
1007                                         now.abs_value);
1008     }
1009 #if DEBUG_UDP
1010     LOG (GNUNET_ERROR_TYPE_DEBUG,
1011                 "UDP processes %u-byte fragment from `%s'\n",
1012                 (unsigned int) ntohs (msg->size),
1013                 GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1014 #endif
1015
1016     if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (rc->defrag, msg))
1017     {
1018       /* keep this 'rc' from expiring */
1019       GNUNET_CONTAINER_heap_update_cost (plugin->defrags, rc->hnode,
1020                                          (GNUNET_CONTAINER_HeapCostType)
1021                                          now.abs_value);
1022     }
1023     if (GNUNET_CONTAINER_heap_get_size (plugin->defrags) >
1024         UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1025     {
1026       /* remove 'rc' that was inactive the longest */
1027       rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags);
1028       GNUNET_assert (NULL != rc);
1029       GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1030       GNUNET_free (rc);
1031     }
1032     return;
1033   default:
1034     GNUNET_break_op (0);
1035     return;
1036   }
1037 }
1038
1039
1040 /**
1041  * We have been notified that our writeset has something to read.  We don't
1042  * know which socket needs to be read, so we have to check each one
1043  * Then reschedule this function to be called again once more is available.
1044  *
1045  * @param cls the plugin handle
1046  * @param tc the scheduling context (for rescheduling this function again)
1047  */
1048 static void
1049 udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1050 {
1051   struct Plugin *plugin = cls;
1052
1053   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1054   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1055     return;
1056   if ((NULL != plugin->sockv4) &&
1057       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
1058     udp_read (plugin, plugin->sockv4);
1059   if ((NULL != plugin->sockv6) &&
1060       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
1061     udp_read (plugin, plugin->sockv6);
1062   plugin->select_task =
1063       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1064                                    GNUNET_SCHEDULER_NO_TASK,
1065                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1066                                    NULL, &udp_plugin_select, plugin);
1067
1068 }
1069
1070
1071 /**
1072  * Check if the given port is plausible (must be either our listen
1073  * port or our advertised port).  If it is neither, we return
1074  * GNUNET_SYSERR.
1075  *
1076  * @param plugin global variables
1077  * @param in_port port number to check
1078  * @return GNUNET_OK if port is either open_port or adv_port
1079  */
1080 static int
1081 check_port (struct Plugin *plugin, uint16_t in_port)
1082 {
1083   if ((in_port == plugin->port) || (in_port == plugin->aport))
1084     return GNUNET_OK;
1085   return GNUNET_SYSERR;
1086 }
1087
1088
1089 /**
1090  * Function that will be called to check if a binary address for this
1091  * plugin is well-formed and corresponds to an address for THIS peer
1092  * (as per our configuration).  Naturally, if absolutely necessary,
1093  * plugins can be a bit conservative in their answer, but in general
1094  * plugins should make sure that the address does not redirect
1095  * traffic to a 3rd party that might try to man-in-the-middle our
1096  * traffic.
1097  *
1098  * @param cls closure, should be our handle to the Plugin
1099  * @param addr pointer to the address
1100  * @param addrlen length of addr
1101  * @return GNUNET_OK if this is a plausible address for this peer
1102  *         and transport, GNUNET_SYSERR if not
1103  *
1104  */
1105 static int
1106 udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1107 {
1108   struct Plugin *plugin = cls;
1109   struct IPv4UdpAddress *v4;
1110   struct IPv6UdpAddress *v6;
1111
1112   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
1113       (addrlen != sizeof (struct IPv6UdpAddress)))
1114   {
1115     GNUNET_break_op (0);
1116     return GNUNET_SYSERR;
1117   }
1118   if (addrlen == sizeof (struct IPv4UdpAddress))
1119   {
1120     v4 = (struct IPv4UdpAddress *) addr;
1121     if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
1122       return GNUNET_SYSERR;
1123     if (GNUNET_OK !=
1124         GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
1125                                  sizeof (struct in_addr)))
1126       return GNUNET_SYSERR;
1127   }
1128   else
1129   {
1130     v6 = (struct IPv6UdpAddress *) addr;
1131     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1132     {
1133       GNUNET_break_op (0);
1134       return GNUNET_SYSERR;
1135     }
1136     if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
1137       return GNUNET_SYSERR;
1138     if (GNUNET_OK !=
1139         GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
1140                                  sizeof (struct in6_addr)))
1141       return GNUNET_SYSERR;
1142   }
1143   return GNUNET_OK;
1144 }
1145
1146
1147 /**
1148  * Function called for a quick conversion of the binary address to
1149  * a numeric address.  Note that the caller must not free the
1150  * address and that the next call to this function is allowed
1151  * to override the address again.
1152  *
1153  * @param cls closure
1154  * @param addr binary address
1155  * @param addrlen length of the address
1156  * @return string representing the same address
1157  */
1158 static const char *
1159 udp_address_to_string (void *cls, const void *addr, size_t addrlen)
1160 {
1161   static char rbuf[INET6_ADDRSTRLEN + 10];
1162   char buf[INET6_ADDRSTRLEN];
1163   const void *sb;
1164   struct in_addr a4;
1165   struct in6_addr a6;
1166   const struct IPv4UdpAddress *t4;
1167   const struct IPv6UdpAddress *t6;
1168   int af;
1169   uint16_t port;
1170
1171   if (addrlen == sizeof (struct IPv6UdpAddress))
1172   {
1173     t6 = addr;
1174     af = AF_INET6;
1175     port = ntohs (t6->u6_port);
1176     memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1177     sb = &a6;
1178   }
1179   else if (addrlen == sizeof (struct IPv4UdpAddress))
1180   {
1181     t4 = addr;
1182     af = AF_INET;
1183     port = ntohs (t4->u4_port);
1184     memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1185     sb = &a4;
1186   }
1187   else
1188   {
1189     GNUNET_break_op (0);
1190     return NULL;
1191   }
1192   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1193   GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
1194                    buf, port);
1195   return rbuf;
1196 }
1197
1198
1199 /**
1200  * Closure for 'append_port'.
1201  */
1202 struct PrettyPrinterContext
1203 {
1204   /**
1205    * Function to call with the result.
1206    */
1207   GNUNET_TRANSPORT_AddressStringCallback asc;
1208
1209   /**
1210    * Clsoure for 'asc'.
1211    */
1212   void *asc_cls;
1213
1214   /**
1215    * Port to add after the IP address.
1216    */
1217   uint16_t port;
1218 };
1219
1220
1221 /**
1222  * Append our port and forward the result.
1223  *
1224  * @param cls a 'struct PrettyPrinterContext'
1225  * @param hostname result from DNS resolver
1226  */
1227 static void
1228 append_port (void *cls, const char *hostname)
1229 {
1230   struct PrettyPrinterContext *ppc = cls;
1231   char *ret;
1232
1233   if (hostname == NULL)
1234   {
1235     ppc->asc (ppc->asc_cls, NULL);
1236     GNUNET_free (ppc);
1237     return;
1238   }
1239   GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1240   ppc->asc (ppc->asc_cls, ret);
1241   GNUNET_free (ret);
1242 }
1243
1244
1245 /**
1246  * Convert the transports address to a nice, human-readable
1247  * format.
1248  *
1249  * @param cls closure
1250  * @param type name of the transport that generated the address
1251  * @param addr one of the addresses of the host, NULL for the last address
1252  *        the specific address format depends on the transport
1253  * @param addrlen length of the address
1254  * @param numeric should (IP) addresses be displayed in numeric form?
1255  * @param timeout after how long should we give up?
1256  * @param asc function to call on each string
1257  * @param asc_cls closure for asc
1258  */
1259 static void
1260 udp_plugin_address_pretty_printer (void *cls, const char *type,
1261                                    const void *addr, size_t addrlen,
1262                                    int numeric,
1263                                    struct GNUNET_TIME_Relative timeout,
1264                                    GNUNET_TRANSPORT_AddressStringCallback asc,
1265                                    void *asc_cls)
1266 {
1267   struct PrettyPrinterContext *ppc;
1268   const void *sb;
1269   size_t sbs;
1270   struct sockaddr_in a4;
1271   struct sockaddr_in6 a6;
1272   const struct IPv4UdpAddress *u4;
1273   const struct IPv6UdpAddress *u6;
1274   uint16_t port;
1275
1276   if (addrlen == sizeof (struct IPv6UdpAddress))
1277   {
1278     u6 = addr;
1279     memset (&a6, 0, sizeof (a6));
1280     a6.sin6_family = AF_INET6;
1281 #if HAVE_SOCKADDR_IN_SIN_LEN
1282     a6.sin6_len = sizeof (a6);
1283 #endif
1284     a6.sin6_port = u6->u6_port;
1285     memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
1286     port = ntohs (u6->u6_port);
1287     sb = &a6;
1288     sbs = sizeof (a6);
1289   }
1290   else if (addrlen == sizeof (struct IPv4UdpAddress))
1291   {
1292     u4 = addr;
1293     memset (&a4, 0, sizeof (a4));
1294     a4.sin_family = AF_INET;
1295 #if HAVE_SOCKADDR_IN_SIN_LEN
1296     a4.sin_len = sizeof (a4);
1297 #endif
1298     a4.sin_port = u4->u4_port;
1299     a4.sin_addr.s_addr = u4->ipv4_addr;
1300     port = ntohs (u4->u4_port);
1301     sb = &a4;
1302     sbs = sizeof (a4);
1303   }
1304   else
1305   {
1306     /* invalid address */
1307     GNUNET_break_op (0);
1308     asc (asc_cls, NULL);
1309     return;
1310   }
1311   ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1312   ppc->asc = asc;
1313   ppc->asc_cls = asc_cls;
1314   ppc->port = port;
1315   GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
1316 }
1317
1318
1319 /**
1320  * Our external IP address/port mapping has changed.
1321  *
1322  * @param cls closure, the 'struct LocalAddrList'
1323  * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1324  *     the previous (now invalid) one
1325  * @param addr either the previous or the new public IP address
1326  * @param addrlen actual lenght of the address
1327  */
1328 static void
1329 udp_nat_port_map_callback (void *cls, int add_remove,
1330                            const struct sockaddr *addr, socklen_t addrlen)
1331 {
1332   struct Plugin *plugin = cls;
1333   struct IPv4UdpAddress u4;
1334   struct IPv6UdpAddress u6;
1335   void *arg;
1336   size_t args;
1337
1338   /* convert 'addr' to our internal format */
1339   switch (addr->sa_family)
1340   {
1341   case AF_INET:
1342     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1343     u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1344     u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
1345     arg = &u4;
1346     args = sizeof (u4);
1347     break;
1348   case AF_INET6:
1349     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1350     memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
1351             sizeof (struct in6_addr));
1352     u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1353     arg = &u6;
1354     args = sizeof (u6);
1355     break;
1356   default:
1357     GNUNET_break (0);
1358     return;
1359   }
1360   /* modify our published address list */
1361   plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
1362 }
1363
1364
1365 /**
1366  * The exported method. Makes the core api available via a global and
1367  * returns the udp transport API.
1368  *
1369  * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
1370  * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
1371  */
1372 void *
1373 libgnunet_plugin_transport_udp_init (void *cls)
1374 {
1375   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1376   unsigned long long port;
1377   unsigned long long aport;
1378   struct GNUNET_TRANSPORT_PluginFunctions *api;
1379   struct Plugin *plugin;
1380   int sockets_created;
1381   struct sockaddr_in serverAddrv4;
1382   struct sockaddr_in6 serverAddrv6;
1383   struct sockaddr *serverAddr;
1384   struct sockaddr *addrs[2];
1385   socklen_t addrlens[2];
1386   socklen_t addrlen;
1387   unsigned int tries;
1388   unsigned long long udp_max_bps;
1389
1390   if (GNUNET_OK !=
1391       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
1392                                              &port))
1393     port = 2086;
1394   if (GNUNET_OK !=
1395       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1396                                              "MAX_BPS", &udp_max_bps))
1397     udp_max_bps = 1024 * 1024 * 50;     /* 50 MB/s == infinity for practical purposes */
1398   if (GNUNET_OK !=
1399       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
1400                                              "ADVERTISED_PORT", &aport))
1401     aport = port;
1402   if (port > 65535)
1403   {
1404     LOG (GNUNET_ERROR_TYPE_WARNING,
1405                 _("Given `%s' option is out of range: %llu > %u\n"), "PORT",
1406                 port, 65535);
1407     return NULL;
1408   }
1409   memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1410   memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1411
1412   plugin = GNUNET_malloc (sizeof (struct Plugin));
1413   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
1414                                  GNUNET_BANDWIDTH_value_init ((uint32_t)
1415                                                               udp_max_bps), 30);
1416   plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
1417   plugin->port = port;
1418   plugin->aport = aport;
1419   plugin->env = env;
1420   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1421   api->cls = plugin;
1422
1423   api->send = &udp_plugin_send;
1424   api->disconnect = &udp_disconnect;
1425   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
1426   api->address_to_string = &udp_address_to_string;
1427   api->check_address = &udp_plugin_check_address;
1428
1429   if (GNUNET_YES ==
1430       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1431                                              "BINDTO", &plugin->bind4_address))
1432   {
1433     LOG (GNUNET_ERROR_TYPE_DEBUG,
1434                 "Binding udp plugin to specific address: `%s'\n",
1435                 plugin->bind4_address);
1436     if (1 != inet_pton (AF_INET, plugin->bind4_address, &serverAddrv4.sin_addr))
1437     {
1438       GNUNET_free (plugin->bind4_address);
1439       GNUNET_free (plugin);
1440       GNUNET_free (api);
1441       return NULL;
1442     }
1443   }
1444
1445   if (GNUNET_YES ==
1446       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
1447                                              "BINDTO6", &plugin->bind6_address))
1448   {
1449     LOG (GNUNET_ERROR_TYPE_DEBUG,
1450                 "Binding udp plugin to specific address: `%s'\n",
1451                 plugin->bind6_address);
1452     if (1 !=
1453         inet_pton (AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1454     {
1455       LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
1456                   plugin->bind6_address);
1457       GNUNET_free_non_null (plugin->bind4_address);
1458       GNUNET_free (plugin->bind6_address);
1459       GNUNET_free (plugin);
1460       GNUNET_free (api);
1461       return NULL;
1462     }
1463   }
1464
1465   plugin->defrags =
1466       GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1467   plugin->sessions =
1468       GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
1469                                             * 2);
1470   plugin->inbound_sessions =
1471       GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
1472                                             * 2);
1473   sockets_created = 0;
1474   if ((GNUNET_YES !=
1475        GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "nat",
1476                                              "DISABLEV6")))
1477   {
1478     plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1479     if (NULL == plugin->sockv6)
1480     {
1481       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1482     }
1483     else
1484     {
1485 #if HAVE_SOCKADDR_IN_SIN_LEN
1486       serverAddrv6.sin6_len = sizeof (serverAddrv6);
1487 #endif
1488       serverAddrv6.sin6_family = AF_INET6;
1489       serverAddrv6.sin6_addr = in6addr_any;
1490       serverAddrv6.sin6_port = htons (plugin->port);
1491       addrlen = sizeof (serverAddrv6);
1492       serverAddr = (struct sockaddr *) &serverAddrv6;
1493 #if DEBUG_UDP
1494       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
1495                   ntohs (serverAddrv6.sin6_port));
1496 #endif
1497       tries = 0;
1498       while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
1499              GNUNET_OK)
1500       {
1501         serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);        /* Find a good, non-root port */
1502 #if DEBUG_UDP
1503         LOG (GNUNET_ERROR_TYPE_DEBUG,
1504                     "IPv6 Binding failed, trying new port %d\n",
1505                     ntohs (serverAddrv6.sin6_port));
1506 #endif
1507         tries++;
1508         if (tries > 10)
1509         {
1510           GNUNET_NETWORK_socket_close (plugin->sockv6);
1511           plugin->sockv6 = NULL;
1512           break;
1513         }
1514       }
1515       if (plugin->sockv6 != NULL)
1516       {
1517         addrs[sockets_created] = (struct sockaddr *) &serverAddrv6;
1518         addrlens[sockets_created] = sizeof (serverAddrv6);
1519         sockets_created++;
1520       }
1521     }
1522   }
1523
1524   plugin->mst =
1525       GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
1526   plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1527   if (NULL == plugin->sockv4)
1528   {
1529     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
1530   }
1531   else
1532   {
1533 #if HAVE_SOCKADDR_IN_SIN_LEN
1534     serverAddrv4.sin_len = sizeof (serverAddrv4);
1535 #endif
1536     serverAddrv4.sin_family = AF_INET;
1537     serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1538     serverAddrv4.sin_port = htons (plugin->port);
1539     addrlen = sizeof (serverAddrv4);
1540     serverAddr = (struct sockaddr *) &serverAddrv4;
1541 #if DEBUG_UDP
1542     LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
1543                 ntohs (serverAddrv4.sin_port));
1544 #endif
1545     tries = 0;
1546     while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
1547            GNUNET_OK)
1548     {
1549       serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);   /* Find a good, non-root port */
1550 #if DEBUG_UDP
1551       LOG (GNUNET_ERROR_TYPE_DEBUG,
1552                   "IPv4 Binding failed, trying new port %d\n",
1553                   ntohs (serverAddrv4.sin_port));
1554 #endif
1555       tries++;
1556       if (tries > 10)
1557       {
1558         GNUNET_NETWORK_socket_close (plugin->sockv4);
1559         plugin->sockv4 = NULL;
1560         break;
1561       }
1562     }
1563     if (plugin->sockv4 != NULL)
1564     {
1565       addrs[sockets_created] = (struct sockaddr *) &serverAddrv4;
1566       addrlens[sockets_created] = sizeof (serverAddrv4);
1567       sockets_created++;
1568     }
1569   }
1570
1571   plugin->rs = GNUNET_NETWORK_fdset_create ();
1572   GNUNET_NETWORK_fdset_zero (plugin->rs);
1573   if (NULL != plugin->sockv4)
1574     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4);
1575   if (NULL != plugin->sockv6)
1576     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6);
1577
1578   plugin->select_task =
1579       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1580                                    GNUNET_SCHEDULER_NO_TASK,
1581                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1582                                    NULL, &udp_plugin_select, plugin);
1583   if (sockets_created == 0)
1584     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
1585   plugin->nat =
1586       GNUNET_NAT_register (env->cfg, GNUNET_NO, port, sockets_created,
1587                            (const struct sockaddr **) addrs, addrlens,
1588                            &udp_nat_port_map_callback, NULL, plugin);
1589   return api;
1590 }
1591
1592
1593 /**
1594  * Destroy a session, plugin is being unloaded.
1595  *
1596  * @param cls unused
1597  * @param key hash of public key of target peer
1598  * @param value a 'struct PeerSession*' to clean up
1599  * @return GNUNET_OK (continue to iterate)
1600  */
1601 static int
1602 destroy_session (void *cls, const GNUNET_HashCode * key, void *value)
1603 {
1604   struct PeerSession *peer_session = value;
1605
1606   GNUNET_FRAGMENT_context_destroy (peer_session->frag);
1607   GNUNET_free (peer_session);
1608   return GNUNET_OK;
1609 }
1610
1611
1612 /**
1613  * Shutdown the plugin.
1614  *
1615  * @param cls our 'struct GNUNET_TRANSPORT_PluginFunctions'
1616  * @return NULL
1617  */
1618 void *
1619 libgnunet_plugin_transport_udp_done (void *cls)
1620 {
1621   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1622   struct Plugin *plugin = api->cls;
1623   struct ReceiveContext *rc;
1624
1625   /* FIXME: clean up heap and hashmap */
1626   GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &destroy_session,
1627                                          NULL);
1628   GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
1629   plugin->sessions = NULL;
1630   GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions, &destroy_session,
1631                                          NULL);
1632   GNUNET_CONTAINER_multihashmap_destroy (plugin->inbound_sessions);
1633   plugin->inbound_sessions = NULL;
1634   while (NULL != (rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags)))
1635   {
1636     GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1637     GNUNET_free (rc);
1638   }
1639   GNUNET_CONTAINER_heap_destroy (plugin->defrags);
1640
1641   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
1642   {
1643     GNUNET_SCHEDULER_cancel (plugin->select_task);
1644     plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1645   }
1646   if (plugin->sockv4 != NULL)
1647   {
1648     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
1649     plugin->sockv4 = NULL;
1650   }
1651   if (plugin->sockv6 != NULL)
1652   {
1653     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
1654     plugin->sockv6 = NULL;
1655   }
1656   GNUNET_SERVER_mst_destroy (plugin->mst);
1657   GNUNET_NETWORK_fdset_destroy (plugin->rs);
1658   GNUNET_NAT_unregister (plugin->nat);
1659   plugin->nat = NULL;
1660   GNUNET_free (plugin);
1661   GNUNET_free (api);
1662   return NULL;
1663 }
1664
1665 /* end of plugin_transport_udp.c */