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