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