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