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