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 "plugin_transport_http_common.h"
39 #include "microhttpd.h"
42 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_server_init
43 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_server_done
45 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_server_init
46 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done
49 #define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
52 * Encapsulation of all of the state of the plugin.
58 * Session handle for connections.
63 * Stored in a linked list.
68 * Stored in a linked list.
73 * To whom are we talking to (set to our identity
74 * if we are still waiting for the welcome message)
76 struct GNUNET_PeerIdentity target;
79 * Pointer to the global plugin struct.
81 struct HTTP_Server_Plugin *plugin;
84 * next pointer for double linked list
86 struct HTTP_Message *msg_head;
89 * previous pointer for double linked list
91 struct HTTP_Message *msg_tail;
94 * Message stream tokenizer for incoming data
96 struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk;
101 struct ServerConnection *server_recv;
106 struct ServerConnection *server_send;
115 * Encapsulation of all of the state of the plugin.
117 struct HTTP_Server_Plugin
122 struct GNUNET_TRANSPORT_PluginEnvironment *env;
125 * Linked list head of open sessions.
128 struct Session *head;
131 * Linked list tail of open sessions.
133 struct Session *tail;
148 char *external_hostname;
151 * Maximum number of sockets the plugin can use
152 * Each http inbound /outbound connections are two connections
154 unsigned int max_connections;
157 * Current number of sockets the plugin can use
158 * Each http inbound /outbound connections are two connections
160 unsigned int cur_connections;
163 * External hostname the plugin can be connected to, can be different to
164 * the host's FQDN, used e.g. for reverse proxying
169 * External address length
189 * Task calling transport service about external address
191 GNUNET_SCHEDULER_TaskIdentifier notify_ext_task;
194 * NAT handle & address management
196 struct GNUNET_NAT_Handle *nat;
199 * Server semi connections
200 * A full session consists of 2 semi-connections: send and receive
201 * If not both directions are established the server keeps this sessions here
203 struct Session *server_semi_head;
205 struct Session *server_semi_tail;
208 * List of own addresses
212 * IPv4 addresses DLL head
214 struct HttpAddressWrapper *addr_head;
217 * IPv4 addresses DLL tail
219 struct HttpAddressWrapper *addr_tail;
222 * IPv4 server socket to bind to
224 struct sockaddr_in *server_addr_v4;
227 * IPv6 server socket to bind to
229 struct sockaddr_in6 *server_addr_v6;
234 GNUNET_SCHEDULER_TaskIdentifier server_v4_task;
239 GNUNET_SCHEDULER_TaskIdentifier server_v6_task;
242 * The IPv4 server is scheduled to run asap
244 int server_v4_immediately;
247 * The IPv6 server is scheduled to run asap
249 int server_v6_immediately;
254 struct MHD_Daemon *server_v4;
259 struct MHD_Daemon *server_v6;
267 * Use RC4-128 instead of AES:
268 * NONE:+VERS-TLS1.0:+ARCFOUR-128:+SHA1:+RSA:+COMP-NULL
287 * Wrapper to manage addresses
289 struct HttpAddressWrapper
294 struct HttpAddressWrapper *next;
297 * Linked list previous
299 struct HttpAddressWrapper *prev;
307 * Message to send using http
312 * next pointer for double linked list
314 struct HTTP_Message *next;
317 * previous pointer for double linked list
319 struct HTTP_Message *prev;
322 * buffer containing data to send
327 * amount of data already sent
337 * Continuation function to call once the transmission buffer
338 * has again space available. NULL if there is no
339 * continuation to call.
341 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
344 * Closure for transmit_cont.
346 void *transmit_cont_cls;
350 static struct Plugin * p;
354 * Function that can be used by the transport service to transmit
355 * a message using the plugin. Note that in the case of a
356 * peer disconnecting, the continuation MUST be called
357 * prior to the disconnect notification itself. This function
358 * will be called with this peer's HELLO message to initiate
359 * a fresh connection to another peer.
362 * @param session which session must be used
363 * @param msgbuf the message to transmit
364 * @param msgbuf_size number of bytes in 'msgbuf'
365 * @param priority how important is the message (most plugins will
366 * ignore message priority and just FIFO)
367 * @param to how long to wait at most for the transmission (does not
368 * require plugins to discard the message after the timeout,
369 * just advisory for the desired delay; most plugins will ignore
371 * @param cont continuation to call once the message has
372 * been transmitted (or if the transport is ready
373 * for the next transmission call; or if the
374 * peer disconnected...); can be NULL
375 * @param cont_cls closure for cont
376 * @return number of bytes used (on the physical network, with overheads);
377 * -1 on hard errors (i.e. address invalid); 0 is a legal value
378 * and does NOT mean that the message was not transmitted (DV)
381 http_server_plugin_send (void *cls,
382 struct Session *session,
383 const char *msgbuf, size_t msgbuf_size,
384 unsigned int priority,
385 struct GNUNET_TIME_Relative to,
386 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
388 struct HTTP_Server_Plugin *plugin = cls;
391 GNUNET_assert (plugin != NULL);
392 GNUNET_assert (session != NULL);
396 /* struct Plugin *plugin = cls; */
403 * Function that can be used to force the plugin to disconnect
404 * from the given peer and cancel all previous transmissions
405 * (and their continuationc).
408 * @param target peer from which to disconnect
411 http_server_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
413 // struct Plugin *plugin = cls;
419 * Another peer has suggested an address for this
420 * peer and transport plugin. Check that this could be a valid
421 * address. If so, consider adding it to the list
425 * @param addr pointer to the address
426 * @param addrlen length of addr
427 * @return GNUNET_OK if this is a plausible address for this peer
431 http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
433 struct HTTP_Server_Plugin *plugin = cls;
434 struct HttpAddressWrapper *w = plugin->addr_head;
436 if (GNUNET_YES == (http_common_cmp_addresses (addr, addrlen, plugin->ext_addr, plugin->ext_addr_len)))
441 if (GNUNET_YES == (http_common_cmp_addresses(addr,
452 * Creates a new outbound session the transport
453 * service will use to send data to the peer
455 * Since HTTP/S server cannot create sessions, always return NULL
457 * @param cls the plugin
458 * @param address the address
459 * @return always NULL
461 static struct Session *
462 http_server_plugin_get_session (void *cls,
463 const struct GNUNET_HELLO_Address *address)
470 * Deleting the session
471 * Must not be used afterwards
475 server_delete_session (struct Session *s)
477 struct HTTP_Server_Plugin *plugin = s->plugin;
478 stop_session_timeout(s);
480 GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s);
481 struct HTTP_Message *msg = s->msg_head;
482 struct HTTP_Message *tmp = NULL;
488 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
489 if (msg->transmit_cont != NULL)
491 msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
497 if (s->msg_tk != NULL)
499 GNUNET_SERVER_mst_destroy (s->msg_tk);
502 GNUNET_free (s->addr);
503 GNUNET_free_non_null (s->server_recv);
504 GNUNET_free_non_null (s->server_send);
510 server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
511 const char *url, const char *method, const char *version,
512 const char *upload_data, size_t * upload_data_size,
513 void **httpSessionCache)
520 server_disconnect_cb (void *cls, struct MHD_Connection *connection,
521 void **httpSessionCache)
528 * Check if incoming connection is accepted.
529 * NOTE: Here every connection is accepted
530 * @param cls plugin as closure
531 * @param addr address of incoming connection
532 * @param addr_len address length of incoming connection
533 * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected
537 server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len)
539 struct HTTP_Server_Plugin *plugin = cls;
541 if (plugin->cur_connections <= plugin->max_connections)
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
546 "Server: Cannot accept new connections\n");
552 server_log (void *arg, const char *fmt, va_list ap)
556 vsnprintf (text, sizeof (text), fmt, ap);
558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server: %s\n", text);
562 * Function that queries MHD's select sets and
563 * starts the task waiting for them.
564 * @param plugin plugin
565 * @param daemon_handle the MHD daemon handle
566 * @return gnunet task identifier
568 static GNUNET_SCHEDULER_TaskIdentifier
569 server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle,
573 * Reschedule the execution of both IPv4 and IPv6 server
574 * @param plugin the plugin
575 * @param server which server to schedule v4 or v6?
576 * @param now GNUNET_YES to schedule execution immediately, GNUNET_NO to wait
580 server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *server, int now)
582 if ((server == plugin->server_v4) && (plugin->server_v4 != NULL))
584 if (GNUNET_YES == plugin->server_v4_immediately)
585 return; /* No rescheduling, server will run asap */
587 if (GNUNET_YES == now)
588 plugin->server_v4_immediately = GNUNET_YES;
590 if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
592 GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
593 plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
595 plugin->server_v4_task = server_schedule (plugin, plugin->server_v4, now);
598 if ((server == plugin->server_v6) && (plugin->server_v6 != NULL))
600 if (GNUNET_YES == plugin->server_v6_immediately)
601 return; /* No rescheduling, server will run asap */
603 if (GNUNET_YES == now)
604 plugin->server_v6_immediately = GNUNET_YES;
606 if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
608 GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
609 plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
611 plugin->server_v6_task = server_schedule (plugin, plugin->server_v6, now);
616 * Call MHD IPv4 to process pending requests and then go back
617 * and schedule the next run.
618 * @param cls plugin as closure
619 * @param tc task context
622 server_v4_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
624 struct HTTP_Server_Plugin *plugin = cls;
626 GNUNET_assert (cls != NULL);
628 plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
629 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
632 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
633 "Running IPv4 server\n");
635 plugin->server_v4_immediately = GNUNET_NO;
636 GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4));
637 server_reschedule (plugin, plugin->server_v4, GNUNET_NO);
642 * Call MHD IPv6 to process pending requests and then go back
643 * and schedule the next run.
644 * @param cls plugin as closure
645 * @param tc task context
648 server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
650 struct HTTP_Server_Plugin *plugin = cls;
652 GNUNET_assert (cls != NULL);
653 plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
654 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
657 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
658 "Running IPv6 server\n");
660 plugin->server_v6_immediately = GNUNET_NO;
661 GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6));
662 server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
667 * Function that queries MHD's select sets and
668 * starts the task waiting for them.
669 * @param plugin plugin
670 * @param daemon_handle the MHD daemon handle
671 * @return gnunet task identifier
673 static GNUNET_SCHEDULER_TaskIdentifier
674 server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle,
677 GNUNET_SCHEDULER_TaskIdentifier ret;
681 struct GNUNET_NETWORK_FDSet *wrs;
682 struct GNUNET_NETWORK_FDSet *wws;
683 struct GNUNET_NETWORK_FDSet *wes;
685 unsigned MHD_LONG_LONG timeout;
686 static unsigned long long last_timeout = 0;
689 struct GNUNET_TIME_Relative tv;
691 ret = GNUNET_SCHEDULER_NO_TASK;
695 wrs = GNUNET_NETWORK_fdset_create ();
696 wes = GNUNET_NETWORK_fdset_create ();
697 wws = GNUNET_NETWORK_fdset_create ();
699 GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
700 haveto = MHD_get_timeout (daemon_handle, &timeout);
701 if (haveto == MHD_YES)
703 if (timeout != last_timeout)
706 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
707 "SELECT Timeout changed from %llu to %llu\n",
708 last_timeout, timeout);
710 last_timeout = timeout;
712 tv.rel_value = (uint64_t) timeout;
715 tv = GNUNET_TIME_UNIT_SECONDS;
716 /* Force immediate run, since we have outbound data to send */
717 if (now == GNUNET_YES)
718 tv = GNUNET_TIME_UNIT_MILLISECONDS;
719 GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
720 GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
721 GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
723 if (daemon_handle == plugin->server_v4)
725 if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
727 GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
728 plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
731 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
732 "Scheduling IPv4 server task in %llu ms\n", tv);
735 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
737 &server_v4_run, plugin);
739 if (daemon_handle == plugin->server_v6)
741 if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
743 GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
744 plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
747 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
748 "Scheduling IPv6 server task in %llu ms\n", tv);
751 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
753 &server_v6_run, plugin);
755 GNUNET_NETWORK_fdset_destroy (wrs);
756 GNUNET_NETWORK_fdset_destroy (wws);
757 GNUNET_NETWORK_fdset_destroy (wes);
764 server_load_file (const char *file)
766 struct GNUNET_DISK_FileHandle *gn_file;
770 if (GNUNET_OK != GNUNET_DISK_file_size (file,
771 &fsize, GNUNET_NO, GNUNET_YES))
773 text = GNUNET_malloc (fsize + 1);
775 GNUNET_DISK_file_open (file, GNUNET_DISK_OPEN_READ,
776 GNUNET_DISK_PERM_USER_READ);
782 if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fsize))
785 GNUNET_DISK_file_close (gn_file);
789 GNUNET_DISK_file_close (gn_file);
798 server_load_certificate (struct HTTP_Server_Plugin *plugin)
805 /* Get crypto init string from config
806 * If not present just use default values */
809 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
812 &plugin->crypto_init))
813 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
814 "Using crypto init string `%s'\n",
815 plugin->crypto_init);
817 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
818 "Using default crypto init string \n");
821 GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
822 "KEY_FILE", &key_file))
824 key_file = GNUNET_strdup ("https_key.key");
828 GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
829 "CERT_FILE", &cert_file))
831 GNUNET_asprintf (&cert_file, "%s", "https_cert.crt");
834 /* read key & certificates from file */
835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
836 "Trying to loading TLS certificate from key-file `%s' cert-file`%s'\n",
837 key_file, cert_file);
839 plugin->key = server_load_file (key_file);
840 plugin->cert = server_load_file (cert_file);
842 if ((plugin->key == NULL) || (plugin->cert == NULL))
844 struct GNUNET_OS_Process *cert_creation;
846 GNUNET_free_non_null (plugin->key);
848 GNUNET_free_non_null (plugin->cert);
851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
852 "No usable TLS certificate found, creating certificate\n");
855 GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
856 "gnunet-transport-certificate-creation",
857 "gnunet-transport-certificate-creation",
858 key_file, cert_file, NULL);
859 if (cert_creation == NULL)
861 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
863 ("Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started!\n"));
864 GNUNET_free (key_file);
865 GNUNET_free (cert_file);
867 GNUNET_free_non_null (plugin->key);
869 GNUNET_free_non_null (plugin->cert);
871 GNUNET_free_non_null (plugin->crypto_init);
872 plugin->crypto_init = NULL;
874 return GNUNET_SYSERR;
876 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (cert_creation));
877 GNUNET_OS_process_destroy (cert_creation);
879 plugin->key = server_load_file (key_file);
880 plugin->cert = server_load_file (cert_file);
883 if ((plugin->key == NULL) || (plugin->cert == NULL))
885 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
887 ("No usable TLS certificate found and creating one failed!\n"),
889 GNUNET_free (key_file);
890 GNUNET_free (cert_file);
892 GNUNET_free_non_null (plugin->key);
894 GNUNET_free_non_null (plugin->cert);
896 GNUNET_free_non_null (plugin->crypto_init);
897 plugin->crypto_init = NULL;
899 return GNUNET_SYSERR;
901 GNUNET_free (key_file);
902 GNUNET_free (cert_file);
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
909 server_start (struct HTTP_Server_Plugin *plugin)
911 unsigned int timeout;
912 GNUNET_assert (NULL != plugin);
915 if (GNUNET_SYSERR == server_load_certificate (plugin))
917 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
918 "Could not load or create server certificate! Loading plugin failed!\n");
919 return GNUNET_SYSERR;
924 #if MHD_VERSION >= 0x00090E00
925 timeout = HTTP_NOT_VALIDATED_TIMEOUT.rel_value / 1000;
926 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
927 "MHD can set timeout per connection! Default time out %u sec.\n",
930 timeout = GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000;
931 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
932 "MHD cannot set timeout per connection! Default time out %u sec.\n",
935 plugin->server_v4 = NULL;
936 if (plugin->use_ipv4 == GNUNET_YES)
938 plugin->server_v4 = MHD_start_daemon (
945 MHD_NO_FLAG, plugin->port,
946 &server_accept_cb, plugin,
947 &server_access_cb, plugin,
948 MHD_OPTION_SOCK_ADDR,
949 (struct sockaddr_in *)
950 plugin->server_addr_v4,
951 MHD_OPTION_CONNECTION_LIMIT,
953 plugin->max_connections,
955 MHD_OPTION_HTTPS_PRIORITIES,
957 MHD_OPTION_HTTPS_MEM_KEY,
959 MHD_OPTION_HTTPS_MEM_CERT,
962 MHD_OPTION_CONNECTION_TIMEOUT,
964 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
966 GNUNET_SERVER_MAX_MESSAGE_SIZE),
967 MHD_OPTION_NOTIFY_COMPLETED,
968 &server_disconnect_cb, plugin,
969 MHD_OPTION_EXTERNAL_LOGGER,
970 server_log, NULL, MHD_OPTION_END);
972 plugin->server_v6 = NULL;
973 if (plugin->use_ipv6 == GNUNET_YES)
975 plugin->server_v6 = MHD_start_daemon (
982 MHD_USE_IPv6, plugin->port,
983 &server_accept_cb, plugin,
984 &server_access_cb, plugin,
985 MHD_OPTION_SOCK_ADDR,
986 (struct sockaddr_in6 *)
987 plugin->server_addr_v6,
988 MHD_OPTION_CONNECTION_LIMIT,
990 plugin->max_connections,
992 MHD_OPTION_HTTPS_PRIORITIES,
994 MHD_OPTION_HTTPS_MEM_KEY,
996 MHD_OPTION_HTTPS_MEM_CERT,
999 MHD_OPTION_CONNECTION_TIMEOUT,
1001 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
1003 GNUNET_SERVER_MAX_MESSAGE_SIZE),
1004 MHD_OPTION_NOTIFY_COMPLETED,
1005 &server_disconnect_cb, plugin,
1006 MHD_OPTION_EXTERNAL_LOGGER,
1007 server_log, NULL, MHD_OPTION_END);
1011 if ((plugin->use_ipv4 == GNUNET_YES) && (plugin->server_v4 == NULL))
1013 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1014 "Failed to start %s IPv4 server component on port %u\n",
1015 plugin->name, plugin->port);
1016 return GNUNET_SYSERR;
1018 server_reschedule (plugin, plugin->server_v4, GNUNET_NO);
1020 if ((plugin->use_ipv6 == GNUNET_YES) && (plugin->server_v6 == NULL))
1022 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1023 "Failed to start %s IPv6 server component on port %u\n",
1024 plugin->name, plugin->port);
1025 return GNUNET_SYSERR;
1027 server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
1028 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1029 "%s server component started on port %u\n", plugin->name,
1036 server_stop (struct HTTP_Server_Plugin *plugin)
1038 struct Session *s = NULL;
1039 struct Session *t = NULL;
1041 struct MHD_Daemon *server_v4_tmp = plugin->server_v4;
1042 plugin->server_v4 = NULL;
1044 struct MHD_Daemon *server_v6_tmp = plugin->server_v6;
1045 plugin->server_v6 = NULL;
1047 if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
1049 GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
1050 plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
1053 if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
1055 GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
1056 plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
1059 if (server_v6_tmp != NULL)
1061 MHD_stop_daemon (server_v4_tmp);
1063 if (server_v6_tmp != NULL)
1065 MHD_stop_daemon (server_v6_tmp);
1068 /* cleaning up semi-sessions never propagated */
1069 s = plugin->server_semi_head;
1073 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1074 "Deleting semi-sessions %p\n", s);
1077 struct HTTP_Message *msg = s->msg_head;
1078 struct HTTP_Message *tmp = NULL;
1084 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
1085 if (msg->transmit_cont != NULL)
1087 msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
1093 server_delete_session (s);
1100 GNUNET_free_non_null (plugin->crypto_init);
1101 GNUNET_free_non_null (plugin->cert);
1102 GNUNET_free_non_null (plugin->key);
1105 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1106 "%s server component stopped\n", plugin->name);
1110 server_add_address (void *cls, int add_remove, const struct sockaddr *addr,
1113 struct HTTP_Server_Plugin *plugin = cls;
1114 struct HttpAddressWrapper *w = NULL;
1116 if ((AF_INET == addr->sa_family) && (GNUNET_NO == plugin->use_ipv4))
1119 if ((AF_INET6 == addr->sa_family) && (GNUNET_NO == plugin->use_ipv6))
1122 w = GNUNET_malloc (sizeof (struct HttpAddressWrapper));
1123 w->addr = http_common_address_from_socket (plugin->protocol, addr, addrlen);
1124 if (NULL == w->addr)
1129 w->addrlen = http_common_address_get_size (w->addr);
1131 GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w);
1132 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1133 "Notifying transport to add address `%s'\n",
1134 http_common_plugin_address_to_string(NULL, w->addr, w->addrlen));
1136 plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen);
1141 server_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
1144 struct HTTP_Server_Plugin *plugin = cls;
1145 struct HttpAddressWrapper *w = plugin->addr_head;
1147 void * saddr = http_common_address_from_socket (plugin->protocol, addr, addrlen);
1150 saddr_len = http_common_address_get_size (saddr);
1154 if (GNUNET_YES == http_common_cmp_addresses(w->addr, w->addrlen, saddr, saddr_len))
1158 GNUNET_free (saddr);
1163 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1164 "Notifying transport to remove address `%s'\n",
1165 http_common_plugin_address_to_string (NULL, w->addr, w->addrlen));
1166 GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
1167 plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen);
1168 GNUNET_free (w->addr);
1175 * Our external IP address/port mapping has changed.
1177 * @param cls closure, the 'struct LocalAddrList'
1178 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1179 * the previous (now invalid) one
1180 * @param addr either the previous or the new public IP address
1181 * @param addrlen actual lenght of the address
1184 server_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
1187 GNUNET_assert (cls != NULL);
1188 struct HTTP_Server_Plugin *plugin = cls;
1190 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1191 "NPMC called %s to address `%s'\n",
1192 (add_remove == GNUNET_NO) ? "remove" : "add",
1193 GNUNET_a2s (addr, addrlen));
1198 server_add_address (cls, add_remove, addr, addrlen);
1201 server_remove_address (cls, add_remove, addr, addrlen);
1208 server_get_addresses (struct HTTP_Server_Plugin *plugin,
1209 const char *serviceName,
1210 const struct GNUNET_CONFIGURATION_Handle *cfg,
1211 struct sockaddr ***addrs, socklen_t ** addr_lens)
1214 unsigned long long port;
1215 struct addrinfo hints;
1216 struct addrinfo *res;
1217 struct addrinfo *pos;
1218 struct addrinfo *next;
1222 struct sockaddr **saddrs;
1223 socklen_t *saddrlens;
1229 disablev6 = !plugin->use_ipv6;
1232 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT"))
1234 GNUNET_break (GNUNET_OK ==
1235 GNUNET_CONFIGURATION_get_value_number (cfg, serviceName,
1239 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1241 ("Require valid port number for service in configuration!\n"));
1242 return GNUNET_SYSERR;
1247 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
1248 "Starting in listen only mode\n");
1249 return -1; /* listen only */
1253 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO"))
1255 GNUNET_break (GNUNET_OK ==
1256 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName,
1257 "BINDTO", &hostname));
1262 if (hostname != NULL)
1264 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1265 "Resolving `%s' since that is where `%s' will bind to.\n",
1266 hostname, serviceName);
1267 memset (&hints, 0, sizeof (struct addrinfo));
1269 hints.ai_family = AF_INET;
1270 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"),
1274 hostname, gai_strerror (ret));
1275 GNUNET_free (hostname);
1276 return GNUNET_SYSERR;
1280 while (NULL != (pos = next))
1282 next = pos->ai_next;
1283 if ((disablev6) && (pos->ai_family == AF_INET6))
1289 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1290 _("Failed to find %saddress for `%s'.\n"),
1291 disablev6 ? "IPv4 " : "", hostname);
1293 GNUNET_free (hostname);
1294 return GNUNET_SYSERR;
1297 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1298 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1301 while (NULL != (pos = next))
1303 next = pos->ai_next;
1304 if ((disablev6) && (pos->ai_family == AF_INET6))
1306 if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0))
1307 continue; /* not TCP */
1308 if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0))
1309 continue; /* huh? */
1310 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1311 "Service will bind to `%s'\n", GNUNET_a2s (pos->ai_addr,
1313 if (pos->ai_family == AF_INET)
1315 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
1316 saddrlens[i] = pos->ai_addrlen;
1317 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1318 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1319 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1323 GNUNET_assert (pos->ai_family == AF_INET6);
1324 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
1325 saddrlens[i] = pos->ai_addrlen;
1326 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1327 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1328 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1332 GNUNET_free (hostname);
1338 /* will bind against everything, just set port */
1344 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1345 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1347 saddrlens[i] = sizeof (struct sockaddr_in);
1348 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1349 #if HAVE_SOCKADDR_IN_SIN_LEN
1350 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1352 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1353 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1359 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1360 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1362 saddrlens[i] = sizeof (struct sockaddr_in6);
1363 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1364 #if HAVE_SOCKADDR_IN_SIN_LEN
1365 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1367 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1368 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1370 saddrlens[i] = sizeof (struct sockaddr_in);
1371 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1372 #if HAVE_SOCKADDR_IN_SIN_LEN
1373 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1375 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1376 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1380 *addr_lens = saddrlens;
1385 server_start_report_addresses (struct HTTP_Server_Plugin *plugin)
1387 int res = GNUNET_OK;
1388 struct sockaddr **addrs;
1389 socklen_t *addrlens;
1391 res = server_get_addresses (plugin,
1392 plugin->name, plugin->env->cfg,
1394 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1395 _("Found %u addresses to report to NAT service\n"), res);
1397 if (GNUNET_SYSERR == res)
1404 GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port,
1406 (const struct sockaddr **) addrs, addrlens,
1407 &server_nat_port_map_callback, NULL, plugin);
1411 GNUNET_assert (addrs[res] != NULL);
1412 GNUNET_free (addrs[res]);
1414 GNUNET_free_non_null (addrs);
1415 GNUNET_free_non_null (addrlens);
1420 server_stop_report_addresses (struct HTTP_Server_Plugin *plugin)
1422 /* Stop NAT handle */
1423 if (NULL != plugin->nat)
1424 GNUNET_NAT_unregister (plugin->nat);
1426 /* Clean up addresses */
1427 struct HttpAddressWrapper *w;
1429 while (plugin->addr_head != NULL)
1431 w = plugin->addr_head;
1432 GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
1433 GNUNET_free (w->addr);
1440 * Check if IPv6 supported on this system
1443 server_check_ipv6_support (struct HTTP_Server_Plugin *plugin)
1445 struct GNUNET_NETWORK_Handle *desc = NULL;
1446 int res = GNUNET_NO;
1448 /* Probe IPv6 support */
1449 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1452 if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
1455 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1457 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
1459 ("Disabling IPv6 since it is not supported on this system!\n"));
1464 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1468 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1469 "Testing IPv6 on this system: %s\n",
1470 (res == GNUNET_YES) ? "successful" : "failed");
1476 * Function called when the service shuts down. Unloads our plugins
1477 * and cancels pending validations.
1479 * @param cls closure, unused
1480 * @param tc task context (unused)
1483 server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1485 struct HTTP_Server_Plugin *plugin = cls;
1487 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
1489 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1492 GNUNET_asprintf(&plugin->ext_addr, "%s://%s", plugin->protocol, plugin->external_hostname);
1493 plugin->ext_addr_len = strlen (plugin->ext_addr) + 1;
1494 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1495 "Notifying transport about external hostname address `%s'\n", plugin->ext_addr);
1496 plugin->env->notify_address (plugin->env->cls, GNUNET_YES, plugin->ext_addr, plugin->ext_addr_len );
1501 server_configure_plugin (struct HTTP_Server_Plugin *plugin)
1503 unsigned long long port;
1504 unsigned long long max_connections;
1505 char *bind4_address = NULL;
1506 char *bind6_address = NULL;
1509 if (GNUNET_CONFIGURATION_have_value
1510 (plugin->env->cfg, plugin->name, "USE_IPv4"))
1513 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
1517 plugin->use_ipv4 = GNUNET_YES;
1518 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1519 _("IPv4 support is %s\n"),
1520 (plugin->use_ipv4 == GNUNET_YES) ? "enabled" : "disabled");
1523 if (GNUNET_CONFIGURATION_have_value
1524 (plugin->env->cfg, plugin->name, "USE_IPv6"))
1527 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
1531 plugin->use_ipv6 = GNUNET_YES;
1532 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1533 _("IPv6 support is %s\n"),
1534 (plugin->use_ipv6 == GNUNET_YES) ? "enabled" : "disabled");
1536 if ((plugin->use_ipv4 == GNUNET_NO) && (plugin->use_ipv6 == GNUNET_NO))
1538 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1540 ("Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"),
1542 return GNUNET_SYSERR;
1545 /* Reading port number from config file */
1547 GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
1548 "PORT", &port)) || (port > 65535))
1550 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1551 _("Port is required! Fix in configuration\n"),
1553 return GNUNET_SYSERR;
1555 plugin->port = port;
1557 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1558 _("Using port %u\n"), plugin->port);
1560 if ((plugin->use_ipv4 == GNUNET_YES) &&
1561 (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
1562 plugin->name, "BINDTO", &bind4_address)))
1564 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1565 "Binding %s plugin to specific IPv4 address: `%s'\n",
1566 plugin->protocol, bind4_address);
1567 plugin->server_addr_v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
1568 if (1 != inet_pton (AF_INET, bind4_address,
1569 &plugin->server_addr_v4->sin_addr))
1571 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1573 ("Specific IPv4 address `%s' in configuration file is invalid!\n"),
1575 GNUNET_free (bind4_address);
1576 GNUNET_free (plugin->server_addr_v4);
1577 plugin->server_addr_v4 = NULL;
1578 return GNUNET_SYSERR;
1582 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1583 _("Binding to IPv4 address %s\n"), bind4_address);
1584 plugin->server_addr_v4->sin_family = AF_INET;
1585 plugin->server_addr_v4->sin_port = htons (plugin->port);
1587 GNUNET_free (bind4_address);
1590 if ((plugin->use_ipv6 == GNUNET_YES) &&
1592 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
1593 "BINDTO6", &bind6_address)))
1595 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1596 "Binding %s plugin to specific IPv6 address: `%s'\n",
1597 plugin->protocol, bind6_address);
1598 plugin->server_addr_v6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
1600 inet_pton (AF_INET6, bind6_address, &plugin->server_addr_v6->sin6_addr))
1602 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1604 ("Specific IPv6 address `%s' in configuration file is invalid!\n"),
1606 GNUNET_free (bind6_address);
1607 GNUNET_free (plugin->server_addr_v6);
1608 plugin->server_addr_v6 = NULL;
1609 return GNUNET_SYSERR;
1613 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1614 _("Binding to IPv6 address %s\n"), bind6_address);
1615 plugin->server_addr_v6->sin6_family = AF_INET6;
1616 plugin->server_addr_v6->sin6_port = htons (plugin->port);
1618 GNUNET_free (bind6_address);
1621 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
1622 "EXTERNAL_HOSTNAME", &plugin->external_hostname))
1624 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1625 _("Using external hostname `%s'\n"), plugin->external_hostname);
1626 plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, plugin);
1629 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1630 "No external hostname configured\n");
1633 /* Optional parameters */
1634 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg,
1636 "MAX_CONNECTIONS", &max_connections))
1637 max_connections = 128;
1638 plugin->max_connections = max_connections;
1640 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1641 _("Maximum number of connections is %u\n"),
1642 plugin->max_connections);
1648 * Exit point from the plugin.
1651 LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
1653 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1654 struct HTTP_Server_Plugin *plugin = api->cls;
1656 if (GNUNET_SCHEDULER_NO_TASK != plugin->notify_ext_task)
1658 GNUNET_SCHEDULER_cancel (plugin->notify_ext_task);
1659 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
1662 if (NULL != plugin->ext_addr)
1664 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1665 "Notifying transport to remove address `%s'\n",
1666 http_common_plugin_address_to_string (NULL,
1668 plugin->ext_addr_len));
1669 plugin->env->notify_address (plugin->env->cls,
1672 plugin->ext_addr_len);
1675 /* Stop to report addresses to transport service */
1676 server_stop_report_addresses (plugin);
1678 server_stop (plugin);
1681 GNUNET_free_non_null (plugin->external_hostname);
1682 GNUNET_free_non_null (plugin->ext_addr);
1683 GNUNET_free_non_null (plugin->server_addr_v4);
1684 GNUNET_free_non_null (plugin->server_addr_v6);
1686 GNUNET_free (plugin);
1693 * Entry point for the plugin.
1696 LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
1698 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1699 struct GNUNET_TRANSPORT_PluginFunctions *api;
1700 struct HTTP_Server_Plugin *plugin;
1702 plugin = GNUNET_malloc (sizeof (struct HTTP_Server_Plugin));
1704 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1706 api->send = &http_server_plugin_send;
1707 api->disconnect = &http_server_plugin_disconnect;
1708 api->check_address = &http_server_plugin_address_suggested;
1709 api->get_session = &http_server_plugin_get_session;
1711 api->address_to_string = &http_common_plugin_address_to_string;
1712 api->string_to_address = &http_common_plugin_string_to_address;
1713 api->address_pretty_printer = &http_common_plugin_address_pretty_printer;
1716 plugin->name = "transport-https_server";
1717 plugin->protocol = "https";
1719 plugin->name = "transport-http_server";
1720 plugin->protocol = "http";
1723 /* Configure plugin */
1724 if (GNUNET_SYSERR == server_configure_plugin (plugin))
1726 LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
1730 /* Check IPv6 support */
1731 if (GNUNET_YES == plugin->use_ipv6)
1732 plugin->use_ipv6 = server_check_ipv6_support (plugin);
1734 /* Report addresses to transport service */
1735 server_start_report_addresses (plugin);
1737 if (GNUNET_SYSERR == server_start (plugin))
1739 LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
1749 /* end of plugin_transport_http_server.c */