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.c
23 * @brief http transport service plugin
24 * @author Matthias Wachs
27 #include "plugin_transport_http.h"
30 server_log (void *arg, const char *fmt, va_list ap)
34 vsnprintf (text, sizeof (text), fmt, ap);
36 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "server: %s\n", text);
40 * Check if incoming connection is accepted.
41 * NOTE: Here every connection is accepted
42 * @param cls plugin as closure
43 * @param addr address of incoming connection
44 * @param addr_len address length of incoming connection
45 * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected
49 server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len)
56 * Callback called by MHD when it needs data to send
57 * @param cls current session
58 * @param pos position in buffer
59 * @param buf the buffer to write data to
60 * @param max max number of bytes available in buffer
61 * @return bytes written to buffer
65 server_send_cb (void *cls, uint64_t pos, char *buf, size_t max)
75 server_load_file (const char *file)
77 struct GNUNET_DISK_FileHandle *gn_file;
81 if (0 != STAT (file, &fstat))
83 text = GNUNET_malloc (fstat.st_size + 1);
85 GNUNET_DISK_file_open (file, GNUNET_DISK_OPEN_READ,
86 GNUNET_DISK_PERM_USER_READ);
92 if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fstat.st_size))
95 GNUNET_DISK_file_close (gn_file);
98 text[fstat.st_size] = '\0';
99 GNUNET_DISK_file_close (gn_file);
108 server_load_certificate (struct Plugin *plugin)
115 /* Get crypto init string from config
116 * If not present just use default values */
117 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
118 "CRYPTO_INIT", &plugin->crypto_init);
121 GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
122 "KEY_FILE", &key_file))
124 key_file = "https_key.key";
128 GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
129 "CERT_FILE", &cert_file))
131 cert_file = "https_cert.crt";
134 /* read key & certificates from file */
136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
137 "Loading TLS certificate from key-file `%s' cert-file`%s'\n",
138 key_file, cert_file);
141 plugin->key = server_load_file (key_file);
142 plugin->cert = server_load_file (cert_file);
144 if ((plugin->key == NULL) || (plugin->cert == NULL))
146 struct GNUNET_OS_Process *cert_creation;
148 GNUNET_free_non_null (plugin->key);
150 GNUNET_free_non_null (plugin->cert);
154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
155 "No usable TLS certificate found, creating certificate\n");
159 GNUNET_OS_start_process (NULL, NULL,
160 "gnunet-transport-certificate-creation",
161 "gnunet-transport-certificate-creation",
162 key_file, cert_file, NULL);
163 if (cert_creation == NULL)
165 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
167 ("Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started!\n"));
168 GNUNET_free (key_file);
169 GNUNET_free (cert_file);
171 GNUNET_free_non_null (plugin->key);
172 GNUNET_free_non_null (plugin->cert);
173 GNUNET_free_non_null (plugin->crypto_init);
175 return GNUNET_SYSERR;
177 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (cert_creation));
178 GNUNET_OS_process_close (cert_creation);
180 plugin->key = server_load_file (key_file);
181 plugin->cert = server_load_file (cert_file);
184 if ((plugin->key == NULL) || (plugin->cert == NULL))
186 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
188 ("No usable TLS certificate found and creating one failed!\n"),
190 GNUNET_free (key_file);
191 GNUNET_free (cert_file);
193 GNUNET_free_non_null (plugin->key);
194 GNUNET_free_non_null (plugin->cert);
195 GNUNET_free_non_null (plugin->crypto_init);
197 return GNUNET_SYSERR;
199 GNUNET_free (key_file);
200 GNUNET_free (cert_file);
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
211 * Process GET or PUT request received via MHD. For
212 * GET, queue response that will send back our pending
213 * messages. For PUT, process incoming data and send
214 * to GNUnet core. In either case, check if a session
215 * already exists and create a new one if not.
218 server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
219 const char *url, const char *method, const char *version,
220 const char *upload_data, size_t * upload_data_size,
221 void **httpSessionCache)
227 server_disconnect_cb (void *cls, struct MHD_Connection *connection,
228 void **httpSessionCache)
233 server_disconnect (struct Session *s)
239 server_send (struct Session *s, const char *msgbuf, size_t msgbuf_size)
245 server_start (struct Plugin *plugin)
250 res = server_load_certificate (plugin);
251 if (res == GNUNET_SYSERR)
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TABORT\n");
258 plugin->server_v4 = NULL;
259 if (plugin->ipv4 == GNUNET_YES)
261 plugin->server_v4 = MHD_start_daemon (
268 MHD_NO_FLAG, plugin->port,
269 &server_accept_cb, plugin,
270 &server_access_cb, plugin,
271 //MHD_OPTION_SOCK_ADDR,
272 //(struct sockaddr_in *)
273 //plugin->bind4_address,
274 MHD_OPTION_CONNECTION_LIMIT,
276 plugin->max_connections,
278 MHD_OPTION_HTTPS_PRIORITIES,
280 MHD_OPTION_HTTPS_MEM_KEY,
282 MHD_OPTION_HTTPS_MEM_CERT,
285 MHD_OPTION_CONNECTION_TIMEOUT,
287 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
289 GNUNET_SERVER_MAX_MESSAGE_SIZE),
290 MHD_OPTION_NOTIFY_COMPLETED,
291 &server_disconnect_cb, plugin,
292 MHD_OPTION_EXTERNAL_LOGGER,
293 server_log, NULL, MHD_OPTION_END);
294 if (plugin->server_v4 == NULL)
297 plugin->server_v6 = NULL;
298 if (plugin->ipv6 == GNUNET_YES)
300 plugin->server_v6 = MHD_start_daemon (
307 MHD_USE_IPv6, plugin->port,
308 &server_accept_cb, plugin,
309 &server_access_cb, plugin,
310 //MHD_OPTION_SOCK_ADDR,
312 MHD_OPTION_CONNECTION_LIMIT,
314 plugin->max_connections,
316 MHD_OPTION_HTTPS_PRIORITIES,
318 MHD_OPTION_HTTPS_MEM_KEY,
320 MHD_OPTION_HTTPS_MEM_CERT,
323 MHD_OPTION_CONNECTION_TIMEOUT,
325 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
327 GNUNET_SERVER_MAX_MESSAGE_SIZE),
328 MHD_OPTION_NOTIFY_COMPLETED,
329 &server_disconnect_cb, plugin,
330 MHD_OPTION_EXTERNAL_LOGGER,
331 server_log, NULL, MHD_OPTION_END);
333 if (plugin->server_v6 == NULL)
338 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
339 "%s server component started on port %u\n", plugin->name,
346 server_stop (struct Plugin *plugin)
349 if (plugin->server_v4 != NULL)
351 MHD_stop_daemon (plugin->server_v4);
352 plugin->server_v4 = NULL;
354 if (plugin->server_v6 != NULL)
356 MHD_stop_daemon (plugin->server_v6);
357 plugin->server_v6 = NULL;
361 GNUNET_free_non_null (plugin->crypto_init);
362 GNUNET_free_non_null (plugin->cert);
363 GNUNET_free_non_null (plugin->key);
367 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
368 "%s server component stopped\n", plugin->name);
374 /* end of plugin_transport_http.c */