2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file transport/plugin_transport_http_server.c
23 * @brief HTTP/S server transport plugin
24 * @author Matthias Wachs
28 #include "gnunet_protocols.h"
29 #include "gnunet_connection_lib.h"
30 #include "gnunet_server_lib.h"
31 #include "gnunet_service_lib.h"
32 #include "gnunet_statistics_service.h"
33 #include "gnunet_transport_service.h"
34 #include "gnunet_transport_plugin.h"
36 #include "gnunet_container_lib.h"
37 #include "gnunet_nat_lib.h"
38 #include "microhttpd.h"
41 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_server_init
42 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_server_done
44 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_server_init
45 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done
49 #define DEBUG_TEMPLATE GNUNET_EXTRA_LOGGING
52 * After how long do we expire an address that we
53 * learned from another peer if it is not reconfirmed
56 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
60 * Encapsulation of all of the state of the plugin.
66 * Session handle for connections.
71 * To whom are we talking to (set to our identity
72 * if we are still waiting for the welcome message)
74 struct GNUNET_PeerIdentity sender;
77 * Stored in a linked list.
82 * Pointer to the global plugin struct.
84 struct HTTP_Server_Plugin *plugin;
87 * The client (used to identify this connection)
92 * Continuation function to call once the transmission buffer
93 * has again space available. NULL if there is no
94 * continuation to call.
96 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
99 * Closure for transmit_cont.
101 void *transmit_cont_cls;
104 * At what time did we reset last_received last?
106 struct GNUNET_TIME_Absolute last_quota_update;
109 * How many bytes have we received since the "last_quota_update"
112 uint64_t last_received;
115 * Number of bytes per ms that this peer is allowed
123 * Encapsulation of all of the state of the plugin.
125 struct HTTP_Server_Plugin
130 struct GNUNET_TRANSPORT_PluginEnvironment *env;
133 * List of open sessions.
135 struct Session *sessions;
139 char *external_hostname;
142 * Maximum number of sockets the plugin can use
143 * Each http inbound /outbound connections are two connections
145 unsigned int max_connections;
148 * External hostname the plugin can be connected to, can be different to
149 * the host's FQDN, used e.g. for reverse proxying
151 struct HttpAddress *ext_addr;
154 * External address length
174 * Task calling transport service about external address
176 GNUNET_SCHEDULER_TaskIdentifier notify_ext_task;
179 * NAT handle & address management
181 struct GNUNET_NAT_Handle *nat;
184 * List of own addresses
188 * IPv4 addresses DLL head
190 struct HttpAddressWrapper *addr_head;
193 * IPv4 addresses DLL tail
195 struct HttpAddressWrapper *addr_tail;
198 * IPv4 server socket to bind to
200 struct sockaddr_in *server_addr_v4;
203 * IPv6 server socket to bind to
205 struct sockaddr_in6 *server_addr_v6;
211 struct MHD_Daemon *server_v4;
216 struct MHD_Daemon *server_v6;
219 GNUNET_NETWORK_STRUCT_BEGIN
222 * HTTP addresses including a full URI
227 * Length of the address following in NBO
229 uint32_t addr_len GNUNET_PACKED;
234 void *addr GNUNET_PACKED;
236 GNUNET_NETWORK_STRUCT_END
239 * Wrapper to manage addresses
241 struct HttpAddressWrapper
246 struct HttpAddressWrapper *next;
249 * Linked list previous
251 struct HttpAddressWrapper *prev;
253 struct HttpAddress *addr;
258 * Function that can be used by the transport service to transmit
259 * a message using the plugin. Note that in the case of a
260 * peer disconnecting, the continuation MUST be called
261 * prior to the disconnect notification itself. This function
262 * will be called with this peer's HELLO message to initiate
263 * a fresh connection to another peer.
266 * @param session which session must be used
267 * @param msgbuf the message to transmit
268 * @param msgbuf_size number of bytes in 'msgbuf'
269 * @param priority how important is the message (most plugins will
270 * ignore message priority and just FIFO)
271 * @param to how long to wait at most for the transmission (does not
272 * require plugins to discard the message after the timeout,
273 * just advisory for the desired delay; most plugins will ignore
275 * @param cont continuation to call once the message has
276 * been transmitted (or if the transport is ready
277 * for the next transmission call; or if the
278 * peer disconnected...); can be NULL
279 * @param cont_cls closure for cont
280 * @return number of bytes used (on the physical network, with overheads);
281 * -1 on hard errors (i.e. address invalid); 0 is a legal value
282 * and does NOT mean that the message was not transmitted (DV)
285 http_server_plugin_send (void *cls,
286 struct Session *session,
287 const char *msgbuf, size_t msgbuf_size,
288 unsigned int priority,
289 struct GNUNET_TIME_Relative to,
290 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
292 struct HTTP_Server_Plugin *plugin = cls;
295 GNUNET_assert (plugin != NULL);
296 GNUNET_assert (session != NULL);
298 /* struct Plugin *plugin = cls; */
305 * Function that can be used to force the plugin to disconnect
306 * from the given peer and cancel all previous transmissions
307 * (and their continuationc).
310 * @param target peer from which to disconnect
313 http_server_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
315 // struct Plugin *plugin = cls;
321 * Convert the transports address to a nice, human-readable
325 * @param type name of the transport that generated the address
326 * @param addr one of the addresses of the host, NULL for the last address
327 * the specific address format depends on the transport
328 * @param addrlen length of the address
329 * @param numeric should (IP) addresses be displayed in numeric form?
330 * @param timeout after how long should we give up?
331 * @param asc function to call on each string
332 * @param asc_cls closure for asc
335 http_server_plugin_address_pretty_printer (void *cls, const char *type,
336 const void *addr, size_t addrlen,
338 struct GNUNET_TIME_Relative timeout,
339 GNUNET_TRANSPORT_AddressStringCallback
348 * Another peer has suggested an address for this
349 * peer and transport plugin. Check that this could be a valid
350 * address. If so, consider adding it to the list
354 * @param addr pointer to the address
355 * @param addrlen length of addr
356 * @return GNUNET_OK if this is a plausible address for this peer
360 http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
362 /* struct Plugin *plugin = cls; */
364 /* check if the address is plausible; if so,
365 * add it to our list! */
371 * Function called for a quick conversion of the binary address to
372 * a numeric address. Note that the caller must not free the
373 * address and that the next call to this function is allowed
374 * to override the address again.
377 * @param addr binary address
378 * @param addrlen length of the address
379 * @return string representing the same address
382 http_server_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
390 server_find_address (struct HTTP_Server_Plugin *plugin, const struct sockaddr *addr, socklen_t addrlen)
392 struct HttpAddressWrapper *w = NULL;
395 GNUNET_asprintf(&saddr, "%s://%s", plugin->protocol, GNUNET_a2s (addr, addrlen));
396 w = plugin->addr_head;
399 if (0 == strcmp (saddr, w->addr->addr))
409 server_add_address (void *cls, int add_remove, const struct sockaddr *addr,
412 struct HTTP_Server_Plugin *plugin = cls;
413 struct HttpAddressWrapper *w = NULL;
417 GNUNET_asprintf(&saddr, "%s://%s", plugin->protocol, GNUNET_a2s (addr, addrlen));
419 haddrlen = sizeof (struct HttpAddress) + strlen(saddr) + 1;
420 w = GNUNET_malloc (sizeof (struct HttpAddressWrapper));
421 w->addr = GNUNET_malloc (haddrlen);
422 w->addr->addr = &w->addr[1];
423 w->addr->addr_len = htonl (strlen(saddr) + 1);
424 memcpy (w->addr->addr, saddr, strlen(saddr) + 1);
427 GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w);
428 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
429 "Notifying transport to add address `%s'\n", w->addr->addr);
431 plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, haddrlen);
436 server_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
439 struct HTTP_Server_Plugin *plugin = cls;
440 struct HttpAddressWrapper *w = NULL;
443 w = server_find_address (plugin, addr, addrlen);
447 haddrlen = sizeof (struct HttpAddress) + ntohl (w->addr->addr_len);
448 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
449 "Notifying transport to remove address `%s'\n", http_server_plugin_address_to_string (NULL, w->addr, haddrlen));
452 GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
453 plugin->env->notify_address (plugin->env->cls, add_remove, w->addr,
454 sizeof (struct HttpAddress) + ntohl (w->addr->addr_len));
455 GNUNET_free (w->addr);
462 * Our external IP address/port mapping has changed.
464 * @param cls closure, the 'struct LocalAddrList'
465 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
466 * the previous (now invalid) one
467 * @param addr either the previous or the new public IP address
468 * @param addrlen actual lenght of the address
471 server_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
474 GNUNET_assert (cls != NULL);
475 struct HTTP_Server_Plugin *plugin = cls;
477 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
478 "NPMC called %s to address `%s'\n",
479 (add_remove == GNUNET_NO) ? "remove" : "add",
480 GNUNET_a2s (addr, addrlen));
485 server_add_address (cls, add_remove, addr, addrlen);
488 server_remove_address (cls, add_remove, addr, addrlen);
495 server_get_addresses (struct HTTP_Server_Plugin *plugin,
496 const char *serviceName,
497 const struct GNUNET_CONFIGURATION_Handle *cfg,
498 struct sockaddr ***addrs, socklen_t ** addr_lens)
501 unsigned long long port;
502 struct addrinfo hints;
503 struct addrinfo *res;
504 struct addrinfo *pos;
505 struct addrinfo *next;
509 struct sockaddr **saddrs;
510 socklen_t *saddrlens;
516 disablev6 = !plugin->use_ipv6;
519 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT"))
521 GNUNET_break (GNUNET_OK ==
522 GNUNET_CONFIGURATION_get_value_number (cfg, serviceName,
526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
528 ("Require valid port number for service in configuration!\n"));
529 return GNUNET_SYSERR;
534 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
535 "Starting in listen only mode\n");
536 return -1; /* listen only */
540 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO"))
542 GNUNET_break (GNUNET_OK ==
543 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName,
544 "BINDTO", &hostname));
549 if (hostname != NULL)
551 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
552 "Resolving `%s' since that is where `%s' will bind to.\n",
553 hostname, serviceName);
554 memset (&hints, 0, sizeof (struct addrinfo));
556 hints.ai_family = AF_INET;
557 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
560 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"),
561 hostname, gai_strerror (ret));
562 GNUNET_free (hostname);
563 return GNUNET_SYSERR;
567 while (NULL != (pos = next))
570 if ((disablev6) && (pos->ai_family == AF_INET6))
576 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577 _("Failed to find %saddress for `%s'.\n"),
578 disablev6 ? "IPv4 " : "", hostname);
580 GNUNET_free (hostname);
581 return GNUNET_SYSERR;
584 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
585 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
588 while (NULL != (pos = next))
591 if ((disablev6) && (pos->ai_family == AF_INET6))
593 if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0))
594 continue; /* not TCP */
595 if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0))
597 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
598 "Service will bind to `%s'\n", GNUNET_a2s (pos->ai_addr,
600 if (pos->ai_family == AF_INET)
602 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
603 saddrlens[i] = pos->ai_addrlen;
604 saddrs[i] = GNUNET_malloc (saddrlens[i]);
605 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
606 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
610 GNUNET_assert (pos->ai_family == AF_INET6);
611 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
612 saddrlens[i] = pos->ai_addrlen;
613 saddrs[i] = GNUNET_malloc (saddrlens[i]);
614 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
615 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
619 GNUNET_free (hostname);
625 /* will bind against everything, just set port */
631 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
632 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
634 saddrlens[i] = sizeof (struct sockaddr_in);
635 saddrs[i] = GNUNET_malloc (saddrlens[i]);
636 #if HAVE_SOCKADDR_IN_SIN_LEN
637 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
639 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
640 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
646 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
647 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
649 saddrlens[i] = sizeof (struct sockaddr_in6);
650 saddrs[i] = GNUNET_malloc (saddrlens[i]);
651 #if HAVE_SOCKADDR_IN_SIN_LEN
652 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
654 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
655 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
657 saddrlens[i] = sizeof (struct sockaddr_in);
658 saddrs[i] = GNUNET_malloc (saddrlens[i]);
659 #if HAVE_SOCKADDR_IN_SIN_LEN
660 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
662 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
663 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
667 *addr_lens = saddrlens;
672 server_start_report_addresses (struct HTTP_Server_Plugin *plugin)
675 struct sockaddr **addrs;
678 res = server_get_addresses (plugin,
679 plugin->name, plugin->env->cfg,
681 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
682 _("Found %u addresses to report to NAT service\n"), res);
684 if (GNUNET_SYSERR == res)
691 GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port,
693 (const struct sockaddr **) addrs, addrlens,
694 &server_nat_port_map_callback, NULL, plugin);
698 GNUNET_assert (addrs[res] != NULL);
699 GNUNET_free (addrs[res]);
701 GNUNET_free_non_null (addrs);
702 GNUNET_free_non_null (addrlens);
707 server_stop_report_addresses (struct HTTP_Server_Plugin *plugin)
709 /* Stop NAT handle */
710 if (NULL != plugin->nat)
711 GNUNET_NAT_unregister (plugin->nat);
713 /* Clean up addresses */
714 struct HttpAddressWrapper *w;
716 while (plugin->addr_head != NULL)
718 w = plugin->addr_head;
719 GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
720 GNUNET_free (w->addr);
727 * Check if IPv6 supported on this system
730 server_check_ipv6_support (struct HTTP_Server_Plugin *plugin)
732 struct GNUNET_NETWORK_Handle *desc = NULL;
735 /* Probe IPv6 support */
736 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
739 if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
742 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
744 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
746 ("Disabling IPv6 since it is not supported on this system!\n"));
751 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
755 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
756 "Testing IPv6 on this system: %s\n",
757 (res == GNUNET_YES) ? "successful" : "failed");
763 * Function called when the service shuts down. Unloads our plugins
764 * and cancels pending validations.
766 * @param cls closure, unused
767 * @param tc task context (unused)
770 server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
772 struct HTTP_Server_Plugin *plugin = cls;
773 struct HttpAddress *eaddr;
778 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
780 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
783 GNUNET_asprintf(&addr, "%s://%s", plugin->protocol, plugin->external_hostname);
784 uri_len = strlen (addr) + 1;
785 eaddr_len = sizeof (struct HttpAddress) + uri_len;
786 eaddr = GNUNET_malloc (eaddr_len);
787 eaddr->addr_len = htonl (uri_len);
788 eaddr->addr = (void *) &eaddr[1];
789 memcpy (&eaddr->addr, addr, uri_len);
790 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
791 "Notifying transport about external hostname address `%s'\n", addr);
794 plugin->env->notify_address (plugin->env->cls, GNUNET_YES, eaddr, eaddr_len);
795 plugin->ext_addr = eaddr;
796 plugin->ext_addr_len = eaddr_len;
801 server_configure_plugin (struct HTTP_Server_Plugin *plugin)
803 unsigned long long port;
804 unsigned long long max_connections;
805 char *bind4_address = NULL;
806 char *bind6_address = NULL;
809 if (GNUNET_CONFIGURATION_have_value
810 (plugin->env->cfg, plugin->name, "USE_IPv4"))
813 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
817 plugin->use_ipv4 = GNUNET_YES;
818 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
819 _("IPv4 support is %s\n"),
820 (plugin->use_ipv4 == GNUNET_YES) ? "enabled" : "disabled");
823 if (GNUNET_CONFIGURATION_have_value
824 (plugin->env->cfg, plugin->name, "USE_IPv6"))
827 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
831 plugin->use_ipv6 = GNUNET_YES;
832 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
833 _("IPv6 support is %s\n"),
834 (plugin->use_ipv6 == GNUNET_YES) ? "enabled" : "disabled");
836 if ((plugin->use_ipv4 == GNUNET_NO) && (plugin->use_ipv6 == GNUNET_NO))
838 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
840 ("Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"),
842 return GNUNET_SYSERR;
845 /* Reading port number from config file */
847 GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
848 "PORT", &port)) || (port > 65535))
850 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
851 _("Port is required! Fix in configuration\n"),
853 return GNUNET_SYSERR;
857 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
858 _("Using port %u\n"), plugin->port);
860 if ((plugin->use_ipv4 == GNUNET_YES) &&
861 (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
862 plugin->name, "BINDTO", &bind4_address)))
864 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
865 "Binding %s plugin to specific IPv4 address: `%s'\n",
866 plugin->protocol, bind4_address);
867 plugin->server_addr_v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
868 if (1 != inet_pton (AF_INET, bind4_address,
869 &plugin->server_addr_v4->sin_addr))
871 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
873 ("Specific IPv4 address `%s' in configuration file is invalid!\n"),
875 GNUNET_free (bind4_address);
876 GNUNET_free (plugin->server_addr_v4);
877 plugin->server_addr_v4 = NULL;
878 return GNUNET_SYSERR;
882 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
883 _("Binding to IPv4 address %s\n"), bind4_address);
884 plugin->server_addr_v4->sin_family = AF_INET;
885 plugin->server_addr_v4->sin_port = htons (plugin->port);
887 GNUNET_free (bind4_address);
890 if ((plugin->use_ipv6 == GNUNET_YES) &&
892 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
893 "BINDTO6", &bind6_address)))
895 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
896 "Binding %s plugin to specific IPv6 address: `%s'\n",
897 plugin->protocol, bind6_address);
898 plugin->server_addr_v6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
900 inet_pton (AF_INET6, bind6_address, &plugin->server_addr_v6->sin6_addr))
902 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
904 ("Specific IPv6 address `%s' in configuration file is invalid!\n"),
906 GNUNET_free (bind6_address);
907 GNUNET_free (plugin->server_addr_v6);
908 plugin->server_addr_v6 = NULL;
909 return GNUNET_SYSERR;
913 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
914 _("Binding to IPv6 address %s\n"), bind6_address);
915 plugin->server_addr_v6->sin6_family = AF_INET6;
916 plugin->server_addr_v6->sin6_port = htons (plugin->port);
918 GNUNET_free (bind6_address);
921 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
922 "EXTERNAL_HOSTNAME", &plugin->external_hostname))
924 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
925 _("Using external hostname `%s'\n"), plugin->external_hostname);
926 plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, plugin);
929 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
930 "No external hostname configured\n");
933 /* Optional parameters */
934 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg,
936 "MAX_CONNECTIONS", &max_connections))
937 max_connections = 128;
938 plugin->max_connections = max_connections;
940 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
941 _("Maximum number of connections is %u\n"),
942 plugin->max_connections);
949 * Exit point from the plugin.
952 LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
954 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
955 struct HTTP_Server_Plugin *plugin = api->cls;
957 if (GNUNET_SCHEDULER_NO_TASK != plugin->notify_ext_task)
959 GNUNET_SCHEDULER_cancel (plugin->notify_ext_task);
960 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
963 if (NULL != plugin->ext_addr)
965 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
966 "Notifying transport to remove address `%s'\n",
967 http_server_plugin_address_to_string (NULL,
969 plugin->ext_addr_len));
970 plugin->env->notify_address (plugin->env->cls,
973 plugin->ext_addr_len);
976 /* Stop to report addresses to transport service */
977 server_stop_report_addresses (plugin);
980 GNUNET_free_non_null (plugin->external_hostname);
981 GNUNET_free_non_null (plugin->ext_addr);
982 GNUNET_free_non_null (plugin->server_addr_v4);
983 GNUNET_free_non_null (plugin->server_addr_v6);
986 GNUNET_free (plugin);
993 * Entry point for the plugin.
996 LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
998 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
999 struct GNUNET_TRANSPORT_PluginFunctions *api;
1000 struct HTTP_Server_Plugin *plugin;
1002 plugin = GNUNET_malloc (sizeof (struct HTTP_Server_Plugin));
1004 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1006 api->send = &http_server_plugin_send;
1007 api->disconnect = &http_server_plugin_disconnect;
1008 api->address_pretty_printer = &http_server_plugin_address_pretty_printer;
1009 api->check_address = &http_server_plugin_address_suggested;
1010 api->address_to_string = &http_server_plugin_address_to_string;
1013 plugin->name = "transport-https_server";
1014 plugin->protocol = "https";
1016 plugin->name = "transport-http_server";
1017 plugin->protocol = "http";
1020 /* Configure plugin */
1021 if (GNUNET_SYSERR == server_configure_plugin (plugin))
1023 LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
1027 /* Check IPv6 support */
1028 if (GNUNET_YES == plugin->use_ipv6)
1029 plugin->use_ipv6 = server_check_ipv6_support (plugin);
1031 /* Report addresses to transport service */
1032 server_start_report_addresses (plugin);
1040 /* end of plugin_transport_http_server.c */