d3c2bac85cb5af9224944acf400b73c5993b7c3e
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
1 /*
2      This file is part of GNUnet
3      (C) 2010 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 2, 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 transport service
24  * @author Christian Grothoff
25  * @author Nathan Evans
26  */
27
28 #include "platform.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_connection_lib.h"
31 #include "gnunet_os_lib.h"
32 #include "gnunet_peerinfo_service.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_resolver_service.h"
35 #include "gnunet_server_lib.h"
36 #include "gnunet_service_lib.h"
37 #include "gnunet_signatures.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet_transport_service.h"
40 #include "plugin_transport.h"
41 #include "transport.h"
42
43 #define DEBUG_UDP GNUNET_NO
44
45 /**
46  * Handle for request of hostname resolution, non-NULL if pending.
47  */
48 static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
49
50 /**
51  * Message-Packet header.
52  */
53 struct UDPMessage
54 {
55   /**
56    * size of the message, in bytes, including this header.
57    */
58   struct GNUNET_MessageHeader header;
59
60   /**
61    * What is the identity of the sender (GNUNET_hash of public key)
62    */
63   struct GNUNET_PeerIdentity sender;
64
65 };
66
67 /* Forward definition */
68 struct Plugin;
69
70 /**
71  * Session handle for UDP connections.
72  */
73 struct Session
74 {
75
76   /**
77    * Stored in a linked list.
78    */
79   struct Session *next;
80
81   /**
82    * Pointer to the global plugin struct.
83    */
84   struct Plugin *plugin;
85
86   /**
87    * To whom are we talking to (set to our identity
88    */
89   struct GNUNET_PeerIdentity target;
90
91   /**
92    * Address of the other peer if WE initiated the connection
93    * (and hence can be sure what it is), otherwise NULL.
94    */
95   void *connect_addr;
96
97   /**
98    * Length of connect_addr, can be 0.
99    */
100   size_t connect_alen;
101
102   /*
103    * Random challenge number for validation
104    */
105   int challenge;
106
107   /*
108    * Have we received validation (performed ping/pong) from this peer?
109    */
110   unsigned int validated;
111
112   /*
113    * What is the latency of this connection? (Time between ping and pong)
114    */
115   struct GNUNET_TIME_Relative latency;
116
117   /*
118    * At what GNUNET_TIME did we send a ping?
119    */
120   struct GNUNET_TIME_Absolute ping_sent;
121 };
122
123 /**
124  * Encapsulation of all of the state of the plugin.
125  */
126 struct Plugin
127 {
128   /**
129    * Our environment.
130    */
131   struct GNUNET_TRANSPORT_PluginEnvironment *env;
132
133   /**
134    * List of open TCP sessions.
135    */
136   struct Session *sessions;
137
138   /**
139    * Handle for the statistics service.
140    */
141   struct GNUNET_STATISTICS_Handle *statistics;
142
143   /**
144    * Handle to the network service.
145    */
146   struct GNUNET_SERVICE_Context *service;
147
148   /**
149    * ID of task used to update our addresses when one expires.
150    */
151   GNUNET_SCHEDULER_TaskIdentifier address_update_task;
152
153   /**
154    * ID of select task
155    */
156   GNUNET_SCHEDULER_TaskIdentifier select_task;
157
158   /**
159    * Port that we are actually listening on.
160    */
161   uint16_t open_port;
162
163   /**
164    * Port that the user said we would have visible to the
165    * rest of the world.
166    */
167   uint16_t adv_port;
168
169   /*
170    * FD Read set
171    */
172   struct GNUNET_NETWORK_FDSet *rs;
173
174 };
175
176 /**
177  * Message used to ask a peer to validate receipt (to check an address
178  * from a HELLO).  Followed by the address used.  Note that the
179  * recipients response does not affirm that he has this address,
180  * only that he got the challenge message.
181  */
182 struct UDPPingMessage
183 {
184
185   /**
186    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PING
187    */
188   struct GNUNET_MessageHeader header;
189
190   /**
191    * Random challenge number (in network byte order).
192    */
193   uint32_t challenge GNUNET_PACKED;
194
195
196
197 };
198
199
200 /**
201  * Message used to validate a HELLO.  The challenge is included in the
202  * confirmation to make matching of replies to requests possible.  The
203  * signature signs the original challenge number, our public key, the
204  * sender's address (so that the sender can check that the address we
205  * saw is plausible for him and possibly detect a MiM attack) and a
206  * timestamp (to limit replay).<p>
207  *
208  * This message is followed by the address of the
209  * client that we are observing (which is part of what
210  * is being signed).
211  */
212 struct UDPPongMessage
213 {
214   /**
215    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PONG
216    */
217   struct GNUNET_MessageHeader header;
218
219   /**
220    * Random challenge number (in network byte order).
221    */
222   uint32_t challenge GNUNET_PACKED;
223
224   /* Length of addr, appended to end of message */
225   unsigned int addrlen;
226 };
227
228 /* *********** globals ************* */
229
230 /**
231  * the socket that we transmit all data with
232  */
233 static struct GNUNET_NETWORK_Handle *udp_sock;
234
235
236 /**
237  * A (core) Session is to be associated with a transport session. The
238  * transport service may want to know in order to call back on the
239  * core if the connection is being closed.
240  *
241  * @param session the session handle passed along
242  *   from the call to receive that was made by the transport
243  *   layer
244  * @return GNUNET_OK if the session could be associated,
245  *         GNUNET_SYSERR if not.
246  */
247 int
248 udp_associate (struct Session *session)
249 {
250   return GNUNET_SYSERR;         /* UDP connections can never be associated */
251 }
252
253 /**
254  * Disconnect from a remote node.
255  *
256  * @param tsession the session that is closed
257  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
258  */
259 void
260 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
261 {
262   return;
263 }
264
265 /**
266  * Shutdown the server process (stop receiving inbound traffic). Maybe
267  * restarted later!
268  */
269 static int
270 udp_transport_server_stop (void *cls)
271 {
272   struct Plugin *plugin = cls;
273   GNUNET_assert (udp_sock != NULL);
274   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
275     {
276       GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task);
277       plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
278     }
279
280   GNUNET_NETWORK_socket_close (udp_sock);
281   udp_sock = NULL;
282   return GNUNET_OK;
283 }
284
285 static struct Session *
286 find_session (void *cls, const struct GNUNET_PeerIdentity *peer)
287 {
288   struct Plugin *plugin = cls;
289   struct Session *pos;
290   pos = plugin->sessions;
291
292   while (pos != NULL)
293     {
294       if (memcmp (peer, &pos->target, sizeof (struct GNUNET_PeerIdentity)) ==
295           0)
296         return pos;
297       pos = pos->next;
298     }
299
300   return NULL;
301 }
302
303 /**
304  * Function that can be used by the transport service to transmit
305  * a message using the plugin.
306  *
307  * @param cls closure
308  * @param service_context value passed to the transport-service
309  *        to identify the neighbour
310  * @param target who should receive this message
311  * @param priority how important is the message
312  * @param msg the message to transmit
313  * @param timeout when should we time out (give up) if we can not transmit?
314  * @param cont continuation to call once the message has
315  *        been transmitted (or if the transport is ready
316  *        for the next transmission call; or if the
317  *        peer disconnected...)
318  * @param cont_cls closure for cont
319  */
320 static void
321 udp_plugin_send (void *cls,
322                  const struct GNUNET_PeerIdentity *target,
323                  unsigned int priority,
324                  const struct GNUNET_MessageHeader *msg,
325                  struct GNUNET_TIME_Relative timeout,
326                  GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
327 {
328   struct Plugin *plugin = cls;
329   struct Session *session;
330   struct UDPMessage *message;
331   int ssize;
332   size_t sent;
333
334   session = find_session (plugin, target);
335
336   if ((session == NULL) || (udp_sock == NULL))
337     return;
338
339   /* Build the message to be sent */
340   message = GNUNET_malloc (sizeof (struct UDPMessage) + ntohs (msg->size));
341   ssize = sizeof (struct UDPMessage) + ntohs (msg->size);
342
343 #if DEBUG_UDP
344   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
345                    ("In udp_send, ssize is %d\n"), ssize);
346 #endif
347   message->header.size = htons (ssize);
348   message->header.type = htons (0);
349   memcpy (&message->sender, plugin->env->my_identity,
350           sizeof (struct GNUNET_PeerIdentity));
351   memcpy (&message[1], msg, ntohs (msg->size));
352
353   /* Actually send the message */
354   sent =
355     GNUNET_NETWORK_socket_sendto (udp_sock, message, ssize,
356                                   session->connect_addr,
357                                   session->connect_alen);
358
359   if (cont != NULL)
360     {
361       if (sent == GNUNET_SYSERR)
362         cont (cont_cls, target, GNUNET_SYSERR);
363       else
364         cont (cont_cls, target, GNUNET_OK);
365     }
366   GNUNET_free (message);
367   return;
368 }
369
370 /**
371  * We've received a PING from this peer via UDP.
372  * Send back our PONG.
373  *
374  * @param cls closure
375  * @param sender the Identity of the sender
376  * @param message the actual message
377  */
378 static void
379 handle_udp_ping (void *cls,
380                  struct GNUNET_PeerIdentity *sender,
381                  struct sockaddr_storage *addr, size_t addrlen,
382                  const struct GNUNET_MessageHeader *message)
383 {
384   struct Plugin *plugin = cls;
385   const struct UDPPingMessage *ping = (const struct UDPPingMessage *) message;
386   struct UDPPongMessage *pong;
387   struct Session *found;
388
389 #if DEBUG_UDP
390   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
391                    ("handling ping, challenge is %d\n"),
392                    ntohs (ping->challenge));
393 #endif
394   found = find_session (plugin, sender);
395   if (found != NULL)
396     {
397       pong = GNUNET_malloc (sizeof (struct UDPPongMessage) + addrlen);
398       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PONG);
399       pong->header.size = htons (sizeof (struct UDPPongMessage) + addrlen);
400       pong->challenge = ping->challenge;
401       memcpy (&pong[1], addr, addrlen);
402       pong->addrlen = htons (addrlen);
403
404       udp_plugin_send (plugin, sender, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
405                        &pong->header,
406                        GNUNET_TIME_relative_multiply
407                        (GNUNET_TIME_UNIT_SECONDS, 30), NULL, NULL);
408       GNUNET_free (pong);
409     }
410
411   return;
412
413 }
414
415 /**
416  * We've received a PONG from this peer via UDP.
417  * Great. Call validate func if we haven't already
418  * received a PONG.
419  *
420  * @param cls closure
421  * @param client identification of the client
422  * @param message the actual message
423  */
424 static void
425 handle_udp_pong (void *cls,
426                  struct GNUNET_PeerIdentity *sender,
427                  const struct GNUNET_MessageHeader *message)
428 {
429   struct Plugin *plugin = cls;
430   const struct UDPPongMessage *pong = (struct UDPPongMessage *) message;
431   struct Session *found;
432   unsigned int addr_len;
433   struct sockaddr_storage addr;
434
435 #if DEBUG_UDP
436   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _("handling pong\n"));
437 #endif
438   found = find_session (plugin, sender);
439 #if DEBUG_UDP
440   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
441                    ("found->challenge %d, pong->challenge %d\n"),
442                    found->challenge, ntohs (pong->challenge));
443 #endif
444   if ((found != NULL) && (found->challenge == ntohs (pong->challenge)))
445     {
446       found->validated = GNUNET_YES;
447       found->latency =
448         GNUNET_TIME_absolute_get_difference (found->ping_sent,
449                                              GNUNET_TIME_absolute_get ());
450       addr_len = ntohs (pong->addrlen);
451 #if DEBUG_UDP
452       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
453                        ("found associated ping, addr is %u bytes\n"),
454                        addr_len);
455 #endif
456       memcpy (&addr, &pong[1], addr_len);
457       plugin->env->notify_validation (plugin->env->cls, "udp", sender,
458                                       ntohs (pong->challenge),
459                                       (char *) &addr);
460     }
461   else
462     {
463
464 #if DEBUG_UDP
465       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
466                        ("Session not found!\n"));
467 #endif
468     }
469   return;
470 }
471
472 static void
473 udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
474 {
475   struct Plugin *plugin = cls;
476   struct GNUNET_TIME_Relative timeout =
477     GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
478   char *buf;
479   struct UDPMessage *msg;
480   const struct GNUNET_MessageHeader *hdr;
481   struct GNUNET_PeerIdentity *sender;
482   unsigned int buflen;
483   socklen_t fromlen;
484   struct sockaddr_storage addr;
485   ssize_t ret;
486   struct Session *found;
487
488   do
489     {
490       buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_sock);
491
492 #if DEBUG_UDP
493       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
494                        ("we expect to read %u bytes\n"), buflen);
495 #endif
496
497       if (buflen == GNUNET_NO)
498         return;
499
500       buf = GNUNET_malloc (buflen);
501       fromlen = sizeof (addr);
502
503 #if DEBUG_UDP
504       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
505                        ("src_addr_len is %u\n"), fromlen);
506 #endif
507
508       memset (&addr, 0, fromlen);
509       ret =
510         GNUNET_NETWORK_socket_recvfrom (udp_sock, buf, buflen,
511                                         (struct sockaddr *) &addr, &fromlen);
512
513 #if DEBUG_UDP
514       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
515                        ("socket_recv returned %u, src_addr_len is %u\n"), ret,
516                        fromlen);
517 #endif
518
519       if (ret <= 0)
520         {
521           GNUNET_free (buf);
522           return;
523         }
524
525       msg = (struct UDPMessage *) buf;
526
527 #if DEBUG_UDP
528       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
529                        ("header reports message size of %d\n"),
530                        ntohs (msg->header.size));
531
532       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
533                        ("header reports message type of %d\n"),
534                        ntohs (msg->header.type));
535 #endif
536       if (ntohs (msg->header.size) < sizeof (struct UDPMessage))
537         {
538           GNUNET_free (buf);
539           GNUNET_NETWORK_fdset_zero (plugin->rs);
540           GNUNET_NETWORK_fdset_set (plugin->rs, udp_sock);
541           break;
542         }
543       hdr = (const struct GNUNET_MessageHeader *) &msg[1];
544       sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
545       memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
546
547 #if DEBUG_UDP
548       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
549                        ("msg reports message size of %d\n"),
550                        ntohs (hdr->size));
551
552       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
553                        ("msg reports message type of %d\n"),
554                        ntohs (hdr->type));
555 #endif
556
557       if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PING)
558         {
559           handle_udp_ping (plugin, sender, &addr, fromlen, hdr);
560         }
561       else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PONG)
562         {
563           handle_udp_pong (plugin, sender, hdr);
564         }
565       else
566         {
567           found = find_session (plugin, sender);
568           if (found != NULL)
569             plugin->env->receive (plugin->env->cls, found->latency, sender,
570                                   &msg->header);
571           else
572             plugin->env->receive (plugin->env->cls,
573                                   GNUNET_TIME_relative_get_forever (), sender,
574                                   &msg->header);
575         }
576       GNUNET_free (sender);
577       GNUNET_free (buf);
578
579     }
580   while (GNUNET_NETWORK_socket_select (plugin->rs,
581                                        NULL,
582                                        NULL,
583                                        timeout) > 0
584          && GNUNET_NETWORK_fdset_isset (plugin->rs, udp_sock));
585
586   plugin->select_task =
587     GNUNET_SCHEDULER_add_select (plugin->env->sched,
588                                  GNUNET_SCHEDULER_PRIORITY_DEFAULT,
589                                  GNUNET_SCHEDULER_NO_TASK,
590                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
591                                  NULL, &udp_plugin_select, plugin);
592
593 }
594
595 /**
596  * Create a UDP socket.  If possible, use IPv6, otherwise
597  * try IPv4.
598  */
599 static struct GNUNET_NETWORK_Handle *
600 udp_transport_server_start (void *cls)
601 {
602   struct Plugin *plugin = cls;
603   struct GNUNET_NETWORK_Handle *desc;
604   struct sockaddr_in serverAddrv4;
605   struct sockaddr_in6 serverAddrv6;
606   struct sockaddr *serverAddr;
607   socklen_t addrlen;
608
609   desc = NULL;
610   if (GNUNET_YES !=
611       GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD",
612                                             "DISABLE-IPV6"))
613     {
614       desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17);
615       if (desc != NULL)
616         {
617           memset (&serverAddrv6, 0, sizeof (serverAddrv6));
618 #if HAVE_SOCKADDR_IN_SIN_LEN
619           serverAddrv6.sin6_len = sizeof (serverAddrv6);
620 #endif
621           serverAddrv6.sin6_family = AF_INET6;
622           serverAddrv6.sin6_addr = in6addr_any;
623           serverAddrv6.sin6_port = htons (plugin->open_port);
624           addrlen = sizeof (serverAddrv6);
625           serverAddr = (struct sockaddr *) &serverAddrv6;
626         }
627     }
628   if (NULL == desc)
629     {
630       desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
631       if (NULL == desc)
632         {
633           GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
634           return NULL;
635         }
636       else
637         {
638           memset (&serverAddrv4, 0, sizeof (serverAddrv4));
639 #if HAVE_SOCKADDR_IN_SIN_LEN
640           serverAddrv4.sin_len = sizeof (serverAddrv4);
641 #endif
642           serverAddrv4.sin_family = AF_INET;
643           serverAddrv4.sin_addr.s_addr = INADDR_ANY;
644           serverAddrv4.sin_port = htons (plugin->open_port);
645           addrlen = sizeof (serverAddrv4);
646           serverAddr = (struct sockaddr *) &serverAddrv4;
647         }
648     }
649
650   if (desc != NULL)
651     {
652       GNUNET_assert (GNUNET_NETWORK_socket_bind (desc, serverAddr, addrlen) ==
653                      GNUNET_OK);
654     }
655
656   plugin->rs = GNUNET_NETWORK_fdset_create ();
657
658   GNUNET_NETWORK_fdset_zero (plugin->rs);
659   GNUNET_NETWORK_fdset_set (plugin->rs, desc);
660
661   plugin->select_task =
662     GNUNET_SCHEDULER_add_select (plugin->env->sched,
663                                  GNUNET_SCHEDULER_PRIORITY_DEFAULT,
664                                  GNUNET_SCHEDULER_NO_TASK,
665                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
666                                  NULL, &udp_plugin_select, plugin);
667
668   return desc;
669 }
670
671 /**
672  * Function that can be used by the transport service to validate that
673  * another peer is reachable at a particular address (even if we
674  * already have a connection to this peer, this function is required
675  * to establish a new one).
676  *
677  * @param cls closure
678  * @param target who should receive this message
679  * @param challenge challenge code to use
680  * @param addrlen length of the address
681  * @param addr the address
682  * @param timeout how long should we try to transmit these?
683  * @return GNUNET_OK if the transmission has been scheduled
684  */
685 static int
686 udp_plugin_validate (void *cls,
687                      const struct GNUNET_PeerIdentity *target,
688                      uint32_t challenge,
689                      struct GNUNET_TIME_Relative timeout,
690                      const void *addr, size_t addrlen)
691 {
692   struct Plugin *plugin = cls;
693   struct Session *new_session;
694   struct UDPPingMessage *msg;
695
696   if (addrlen <= 0)
697     return GNUNET_SYSERR;
698
699   new_session = GNUNET_malloc (sizeof (struct Session));
700   new_session->connect_addr = GNUNET_malloc (addrlen);
701   memcpy (new_session->connect_addr, addr, addrlen);
702   new_session->connect_alen = addrlen;
703 #if DEBUG_UDP
704   if (memcmp
705       (target, plugin->env->my_identity,
706        sizeof (struct GNUNET_PeerIdentity)) == 0)
707     {
708       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
709                        ("definitely adding self to session list... hmmm\n"));
710     }
711 #endif
712   memcpy (&new_session->target, target, sizeof (struct GNUNET_PeerIdentity));
713   new_session->challenge = challenge;
714   new_session->validated = GNUNET_NO;
715   new_session->latency = GNUNET_TIME_relative_get_zero ();
716   new_session->ping_sent = GNUNET_TIME_absolute_get ();
717   new_session->next = plugin->sessions;
718   plugin->sessions = new_session;
719
720   msg = GNUNET_malloc (sizeof (struct UDPPingMessage));
721   msg->header.size = htons (sizeof (struct UDPPingMessage));
722   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PING);
723   msg->challenge = htons (challenge);
724 #if DEBUG_UDP
725   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
726                    ("In validate, header size is %d, type %d, challenge %u\n"),
727                    ntohs (msg->header.size), ntohs (msg->header.type),
728                    ntohl (msg->challenge));
729 #endif
730   udp_plugin_send (plugin, target, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
731                    &msg->header, timeout, NULL, NULL);
732
733   GNUNET_free (msg);
734   return GNUNET_OK;
735 }
736
737 /**
738  * Convert the transports address to a nice, human-readable
739  * format.
740  *
741  * @param cls closure
742  * @param type name of the transport that generated the address
743  * @param addr one of the addresses of the host, NULL for the last address
744  *        the specific address format depends on the transport
745  * @param addrlen length of the address
746  * @param numeric should (IP) addresses be displayed in numeric form?
747  * @param timeout after how long should we give up?
748  * @param asc function to call on each string
749  * @param asc_cls closure for asc
750  */
751 static void
752 udp_plugin_address_pretty_printer (void *cls,
753                                    const char *type,
754                                    const void *addr,
755                                    size_t addrlen,
756                                    int numeric,
757                                    struct GNUNET_TIME_Relative timeout,
758                                    GNUNET_TRANSPORT_AddressStringCallback asc,
759                                    void *asc_cls)
760 {
761
762 }
763
764 /**
765  * Set a quota for receiving data from the given peer; this is a
766  * per-transport limit.  The transport should limit its read/select
767  * calls to stay below the quota (in terms of incoming data).
768  *
769  * @param cls closure
770  * @param target the peer for whom the quota is given
771  * @param quota_in quota for receiving/sending data in bytes per ms
772  */
773 static void
774 udp_plugin_set_receive_quota (void *cls,
775                               const struct GNUNET_PeerIdentity *target,
776                               uint32_t quota_in)
777 {
778
779 }
780
781 /**
782  * Another peer has suggested an address for this
783  * peer and transport plugin.  Check that this could be a valid
784  * address.  If so, consider adding it to the list
785  * of addresses.
786  *
787  * @param cls closure
788  * @param addr pointer to the address
789  * @param addrlen length of addr
790  * @return GNUNET_OK if this is a plausible address for this peer
791  *         and transport
792  */
793 static int
794 udp_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
795 {
796
797   return GNUNET_SYSERR;
798 }
799
800
801 /**
802  * The exported method. Makes the core api available via a global and
803  * returns the udp transport API.
804  */
805 void *
806 libgnunet_plugin_transport_udp_init (void *cls)
807 {
808   unsigned long long mtu;
809
810   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
811   struct GNUNET_TRANSPORT_PluginFunctions *api;
812   struct Plugin *plugin;
813   struct GNUNET_SERVICE_Context *service;
814   unsigned long long aport;
815   unsigned long long bport;
816
817   service = GNUNET_SERVICE_start ("transport-udp", env->sched, env->cfg);
818   if (service == NULL)
819     {
820       GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "udp", _
821                        ("Failed to start service for `%s' transport plugin.\n"),
822                        "udp");
823       return NULL;
824     }
825   aport = 0;
826   if ((GNUNET_OK !=
827        GNUNET_CONFIGURATION_get_value_number (env->cfg,
828                                               "transport-udp",
829                                               "PORT",
830                                               &bport)) ||
831       (bport > 65535) ||
832       ((GNUNET_OK ==
833         GNUNET_CONFIGURATION_get_value_number (env->cfg,
834                                                "transport-udp",
835                                                "ADVERTISED-PORT",
836                                                &aport)) && (aport > 65535)))
837     {
838       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
839                        "udp",
840                        _
841                        ("Require valid port number for service `%s' in configuration!\n"),
842                        "transport-udp");
843       GNUNET_SERVICE_stop (service);
844       return NULL;
845     }
846   if (aport == 0)
847     aport = bport;
848
849   mtu = 1240;
850   if (mtu < 1200)
851     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
852                      "udp",
853                      _("MTU %llu for `%s' is probably too low!\n"), mtu,
854                      "UDP");
855
856   plugin = GNUNET_malloc (sizeof (struct Plugin));
857   plugin->open_port = bport;
858   plugin->adv_port = aport;
859   plugin->env = env;
860   plugin->statistics = NULL;
861   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
862   plugin->sessions = NULL;
863   api->cls = plugin;
864
865   api->validate = &udp_plugin_validate;
866   api->send = &udp_plugin_send;
867   api->disconnect = &udp_disconnect;
868   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
869   api->set_receive_quota = &udp_plugin_set_receive_quota;
870   api->address_suggested = &udp_plugin_address_suggested;
871   api->cost_estimate = 17;      /* TODO: ATS */
872   plugin->service = service;
873
874   udp_sock = udp_transport_server_start (plugin);
875
876   GNUNET_assert (udp_sock != NULL);
877
878   return api;
879 }
880
881 void *
882 libgnunet_plugin_transport_udp_done (void *cls)
883 {
884   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
885   struct Plugin *plugin = api->cls;
886   struct Session *pos;
887   struct Session *oldpos;
888
889   udp_transport_server_stop (plugin);
890   if (NULL != hostname_dns)
891     {
892       GNUNET_RESOLVER_request_cancel (hostname_dns);
893       hostname_dns = NULL;
894     }
895   GNUNET_SERVICE_stop (plugin->service);
896
897   pos = plugin->sessions;
898   while (pos != NULL)
899     {
900       GNUNET_free (pos->connect_addr);
901       oldpos = pos;
902       pos = pos->next;
903       GNUNET_free (oldpos);
904     }
905
906   GNUNET_NETWORK_fdset_destroy (plugin->rs);
907   GNUNET_free (plugin);
908   GNUNET_free (api);
909   return NULL;
910 }
911
912 /* end of plugin_transport_udp.c */