/*
This file is part of GNUnet
- (C) 2002-2013 Christian Grothoff (and other contributing authors)
+ (C) 2002-2014 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
* @file transport/plugin_transport_http_server.c
* @brief HTTP/S server transport plugin
* @author Matthias Wachs
+ * @author David Barksdale
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_nat_lib.h"
#include "plugin_transport_http_common.h"
#include <microhttpd.h>
+#include <regex.h>
#define _SEND 1
-/**
- * Enable output for debbuging URL's of incoming requests
- */
-#define DEBUG_URL_PARSE GNUNET_NO
-
-
-/**
- * Encapsulation of all of the state of the plugin.
- */
-struct Plugin;
-
/**
* Session handle for connections.
*/
struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk;
/**
- * Client send handle
+ * Client recv handle
*/
struct ServerConnection *server_recv;
/**
* Address
*/
- void *addr;
-
- /**
- * Address length
- */
- size_t addrlen;
+ struct GNUNET_HELLO_Address *address;
/**
* Unique HTTP/S connection tag for this connection
*/
int session_ended;
- /**
- * Are incoming connection established at the moment
- */
- int connect_in_progress;
-
/**
* Absolute time when to receive data again
* Used for receive throttling
* Session timeout task
*/
GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ /**
+ * Should this session get disconnected? GNUNET_YES/NO
+ */
+ int disconnect;
};
*/
int direction;
- /**
- * Should this connection get disconnected? GNUNET_YES/NO
- */
- int disconnect;
-
/**
* For PUT connections: Is this the first or last callback with size 0
+ * For GET connections: Have we sent a message
*/
int connected;
* The MHD daemon
*/
struct MHD_Daemon *mhd_daemon;
+
+ /**
+ * Options requested by peer
+ */
+ uint32_t options;
+#define OPTION_LONG_POLL 1 /* GET request wants long-poll semantics */
};
* External hostname the plugin can be connected to, can be different to
* the host's FQDN, used e.g. for reverse proxying
*/
- struct HttpAddress *ext_addr;
+ struct GNUNET_HELLO_Address *ext_addr;
/**
* Notify transport only about external address
*/
unsigned int external_only;
- /**
- * External address length
- */
- size_t ext_addr_len;
-
/**
* use IPv6
*/
*/
struct MHD_Daemon *server_v6;
+ /**
+ * Regex for parsing URLs
+ */
+ regex_t url_regex;
+
#if BUILD_HTTPS
/**
* Crypto related
GNUNET_break (0);
return GNUNET_SYSERR;
}
- if (NULL == session->server_send)
- {
- if (GNUNET_NO == session->connect_in_progress)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, session->plugin->name,
- "Session %p/connection %p: Sending message with %u bytes to peer `%s' with FAILED\n",
- session, session->server_send,
- msgbuf_size, GNUNET_i2s (&session->target));
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- }
- else
- {
- if (GNUNET_YES == session->server_send->disconnect)
- return GNUNET_SYSERR;
- }
+ if (session->disconnect)
+ return GNUNET_SYSERR;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, session->plugin->name,
if ((NULL != plugin->ext_addr) &&
GNUNET_YES == (http_common_cmp_addresses (addr, addrlen,
- plugin->ext_addr,
- plugin->ext_addr_len)))
+ plugin->ext_addr->address,
+ plugin->ext_addr->address_length)))
{
/* Checking HTTP_OPTIONS_VERIFY_CERTIFICATE option for external hostname */
if ((ntohl (haddr->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE) !=
GNUNET_SERVER_mst_destroy (s->msg_tk);
s->msg_tk = NULL;
}
- GNUNET_free (s->addr);
+ GNUNET_HELLO_address_free (s->address);
GNUNET_free_non_null (s->server_recv);
GNUNET_free_non_null (s->server_send);
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
GNUNET_break (0);
return GNUNET_SYSERR;
}
-
+ s->disconnect = GNUNET_YES;
send = (struct ServerConnection *) s->server_send;
- if (s->server_send != NULL)
+ if (send != NULL)
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
"Server: %p / %p Terminating inbound PUT session to peer `%s'\n",
- s, s->server_send, GNUNET_i2s (&s->target));
+ s, send, GNUNET_i2s (&s->target));
- send->disconnect = GNUNET_YES;
MHD_set_connection_option (send->mhd_conn,
MHD_CONNECTION_OPTION_TIMEOUT,
1);
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
"Server: %p / %p Terminating inbound GET session to peer `%s'\n",
- s, s->server_recv, GNUNET_i2s (&s->target));
+ s, recv, GNUNET_i2s (&s->target));
- recv->disconnect = GNUNET_YES;
MHD_set_connection_option (recv->mhd_conn,
MHD_CONNECTION_OPTION_TIMEOUT,
1);
* GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
* calculate the interval between keepalive packets.
*
- * @param cls closure with the `struct Plugin`
+ * @param cls closure with the `struct HTTP_Server_Plugin`
* @return keepalive factor
*/
static unsigned int
* @param url incoming url
* @param target where to store the target
* @param tag where to store the tag
+ * @param options where to store the options
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static int
server_parse_url (struct HTTP_Server_Plugin *plugin,
const char *url,
struct GNUNET_PeerIdentity *target,
- uint32_t *tag)
+ uint32_t *tag,
+ uint32_t *options)
{
- char * tag_start = NULL;
- char * tag_end = NULL;
- char * target_start = NULL;
- char * separator = NULL;
- unsigned int hash_length;
- unsigned long int ctag;
-
- /* URL parsing
- * URL is valid if it is in the form [prefix with (multiple) '/'][peerid[103];tag]*/
+ regmatch_t matches[4];
+ const char *tag_start;
+ const char *target_start;
+ char *tag_end;
+ char *options_end;
+ size_t hash_length;
+ unsigned long int rc;
+
+ /* URL parsing */
+#define URL_REGEX \
+ ("^.*/([0-9A-V]+);([0-9]+)(,[0-9]+)?$")
if (NULL == url)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
- /* convert tag */
- /* find separator */
- separator = strrchr (url, ';');
-
- if (NULL == separator)
+ if (regexec(&plugin->url_regex, url, 4, matches, 0))
{
- if (DEBUG_URL_PARSE) GNUNET_break (0);
- return GNUNET_SYSERR;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL `%s' did not match regex\n", url);
+ return GNUNET_SYSERR;
}
- tag_start = separator + 1;
- if (strlen (tag_start) == 0)
+ target_start = &url[matches[1].rm_so];
+ tag_start = &url[matches[2].rm_so];
+
+ /* convert tag */
+ rc = strtoul (tag_start, &tag_end, 10);
+ if (&url[matches[2].rm_eo] != tag_end)
{
- /* No tag after separator */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL tag did not line up with submatch\n");
return GNUNET_SYSERR;
}
- ctag = strtoul (tag_start, &tag_end, 10);
- if (ctag == 0)
+ if (rc == 0)
{
- /* tag == 0 , invalid */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL tag is zero\n");
return GNUNET_SYSERR;
}
- if ((ctag == ULONG_MAX) && (ERANGE == errno))
+ if ((rc == ULONG_MAX) && (ERANGE == errno))
{
- /* out of range: > ULONG_MAX */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL tag > ULONG_MAX\n");
return GNUNET_SYSERR;
}
- if (ctag > UINT32_MAX)
+ if (rc > UINT32_MAX)
{
- /* out of range: > UINT32_MAX */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL tag > UINT32_MAX\n");
return GNUNET_SYSERR;
}
- (*tag) = (uint32_t) ctag;
- if (NULL == tag_end)
- {
- /* no char after tag */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (url[strlen(url)] != tag_end[0])
- {
- /* there are more not converted chars after tag */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (DEBUG_URL_PARSE)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Found tag `%u' in url\n", (*tag));
+ (*tag) = (uint32_t)rc;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Found tag `%u' in url\n", *tag);
/* convert peer id */
- target_start = strrchr (url, '/');
- if (NULL == target_start)
- {
- /* no leading '/' */
- target_start = (char *) url;
- }
- target_start++;
- hash_length = separator - target_start;
+ hash_length = matches[1].rm_eo - matches[1].rm_so;
if (hash_length != plugin->peer_id_length)
{
- /* no char after tag */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
- return GNUNET_SYSERR;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL target is %u bytes, expecting %u\n",
+ hash_length, plugin->peer_id_length);
+ return GNUNET_SYSERR;
}
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_public_key_from_string (target_start,
hash_length,
&target->public_key))
- {
- /* hash conversion failed */
- if (DEBUG_URL_PARSE) GNUNET_break (0);
- return GNUNET_SYSERR;
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL target conversion failed\n");
+ return GNUNET_SYSERR;
}
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
plugin->name,
"Found target `%s' in URL\n",
GNUNET_i2s_full (target));
+
+ /* convert options */
+ if (-1 == matches[3].rm_so) {
+ *options = 0;
+ } else {
+ rc = strtoul (&url[matches[3].rm_so + 1], &options_end, 10);
+ if (&url[matches[3].rm_eo] != options_end)
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL options did not line up with submatch\n");
+ return GNUNET_SYSERR;
+ }
+ if ((rc == ULONG_MAX) && (ERANGE == errno))
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL options > ULONG_MAX\n");
+ return GNUNET_SYSERR;
+ }
+ if (rc > UINT32_MAX)
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "URL options > UINT32_MAX\n");
+ return GNUNET_SYSERR;
+ }
+ (*options) = (uint32_t)rc;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Found options `%u' in url\n", *options);
+ }
return GNUNET_OK;
}
struct Session *s = NULL;
struct ServerConnection *sc = NULL;
const union MHD_ConnectionInfo *conn_info;
- struct GNUNET_ATS_Information ats;
struct HttpAddress *addr;
- size_t addr_len;
+
+ struct GNUNET_ATS_Information ats;
struct GNUNET_PeerIdentity target;
+ size_t addr_len;
uint32_t tag = 0;
+ uint32_t options;
int direction = GNUNET_SYSERR;
unsigned int to;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"New %s connection from %s\n", method, url);
- if (GNUNET_SYSERR == server_parse_url (plugin, url, &target, &tag))
+ if (GNUNET_SYSERR == server_parse_url (plugin, url, &target, &tag, &options))
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Invalid url %s\n", url);
else
{
/* create new session */
+ addr = NULL;
switch (conn_info->client_addr->sa_family)
{
case (AF_INET):
s = GNUNET_new (struct Session);
memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity));
s->plugin = plugin;
- s->addr = addr;
- s->addrlen = addr_len;
+ s->address = GNUNET_HELLO_address_allocate (&s->target, PLUGIN_NAME,
+ addr, addr_len, GNUNET_HELLO_ADDRESS_INFO_INBOUND);
s->ats_address_network_type = ats.value;
s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS;
s->tag = tag;
s->server_send = NULL;
s->session_passed = GNUNET_NO;
s->session_ended = GNUNET_NO;
- s->connect_in_progress = GNUNET_YES;
server_start_session_timeout(s);
GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s);
http_common_plugin_address_to_string (NULL,
plugin->protocol,
addr, addr_len));
+ GNUNET_free_non_null (addr);
}
sc = GNUNET_new (struct ServerConnection);
if (conn_info->client_addr->sa_family == AF_INET)
sc->direction = direction;
sc->connected = GNUNET_NO;
sc->session = s;
+ sc->options = options;
if (direction == _SEND)
s->server_send = sc;
if (direction == _RECEIVE)
if ((NULL != s->server_send) && (NULL != s->server_recv))
{
- s->connect_in_progress = GNUNET_NO; /* PUT and GET are connected */
- plugin->env->session_start (NULL, &s->target, PLUGIN_NAME, NULL, 0 ,s, NULL, 0);
+ plugin->env->session_start (NULL, s->address ,s, NULL, 0);
}
if ((NULL == s->server_recv) || (NULL == s->server_send))
server_send_callback (void *cls, uint64_t pos, char *buf, size_t max)
{
struct Session *s = cls;
+ struct ServerConnection *sc;
ssize_t bytes_read = 0;
struct HTTP_Message *msg;
char *stat_txt;
if (GNUNET_NO == server_exist_session (s->plugin, s))
return 0;
+ sc = s->server_send;
+ if (NULL == sc)
+ return 0;
msg = s->msg_head;
if (NULL != msg)
{
}
if (0 < bytes_read)
{
+ sc->connected = GNUNET_YES;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
"Sent %u bytes to peer `%s' with session %p \n", bytes_read, GNUNET_i2s (&s->target), s);
GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers",
GNUNET_STATISTICS_update (s->plugin->env->stats,
stat_txt, bytes_read, GNUNET_NO);
GNUNET_free (stat_txt);
+ } else if ((sc->options & OPTION_LONG_POLL) && sc->connected) {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+ "Completing GET response to peer `%s' with session %p \n",
+ GNUNET_i2s (&s->target), s);
+ return MHD_CONTENT_READER_END_OF_STREAM;
}
return bytes_read;
}
atsi.value = s->ats_address_network_type;
GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED));
-
- delay = plugin->env->receive (plugin->env->cls,
- &s->target,
- message,
- s, NULL, 0);
-
- plugin->env->update_address_metrics (plugin->env->cls,
- &s->target,
- NULL, 0, s, &atsi, 1);
+ delay = plugin->env->receive (plugin->env->cls, s->address, s, message);
+ plugin->env->update_address_metrics (plugin->env->cls, s->address, s, &atsi, 1);
GNUNET_asprintf (&stat_txt, "# bytes received via %s_server", plugin->protocol);
GNUNET_STATISTICS_update (plugin->env->stats,
"Peer `%s' address `%s' next read delayed for %s\n",
GNUNET_i2s (&s->target),
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr, s->addrlen),
+ plugin->protocol, s->address->address,
+ s->address->address_length),
GNUNET_STRINGS_relative_time_to_string (delay,
GNUNET_YES));
}
return GNUNET_OK;
}
+/**
+ * Add headers to a request indicating that we allow Cross-Origin Resource
+ * Sharing.
+ */
+static void
+add_cors_headers(struct MHD_Response *response)
+{
+ MHD_add_response_header (response,
+ "Access-Control-Allow-Origin",
+ "*");
+ MHD_add_response_header (response,
+ "Access-Control-Allow-Methods",
+ "GET, PUT, OPTIONS");
+ MHD_add_response_header (response,
+ "Access-Control-Max-Age",
+ "86400");
+}
/**
* MHD callback for a new incoming connection
GNUNET_assert (cls != NULL);
if (sc == NULL)
{
+ /* CORS pre-flight request */
+ if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method))
+ {
+ response = MHD_create_response_from_buffer (0, NULL,
+ MHD_RESPMEM_PERSISTENT);
+ add_cors_headers(response);
+ res = MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return res;
+ }
/* new connection */
sc = server_lookup_connection (plugin, mhd_connection, url, method);
if (sc != NULL)
MHD_add_response_header (response,
MHD_HTTP_HEADER_CONTENT_TYPE,
"text/html");
+ add_cors_headers(response);
res = MHD_queue_response (mhd_connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response (response);
return res;
s = sc->session;
GNUNET_assert (NULL != s);
/* connection is to be disconnected */
- if (sc->disconnect == GNUNET_YES)
+ if (s->disconnect == GNUNET_YES)
{
/* Sent HTTP/1.1: 200 OK as response */
response = MHD_create_response_from_data (strlen ("Thank you!"),
"Thank you!",
MHD_NO, MHD_NO);
+ add_cors_headers(response);
MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return MHD_YES;
32 * 1024,
&server_send_callback, s,
NULL);
+ add_cors_headers(response);
MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return MHD_YES;
s, sc,
GNUNET_i2s (&s->target),
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr,
- s->addrlen));
+ plugin->protocol, s->address->address,
+ s->address->address_length));
sc->connected = GNUNET_YES;
return MHD_YES;
}
s, sc,
GNUNET_i2s (&s->target),
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr,
- s->addrlen));
+ plugin->protocol, s->address->address,
+ s->address->address_length));
sc->connected = GNUNET_NO;
/* Sent HTTP/1.1: 200 OK as PUT Response\ */
response = MHD_create_response_from_data (strlen ("Thank you!"),
"Thank you!",
MHD_NO, MHD_NO);
+ add_cors_headers(response);
MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return MHD_YES;
s, sc,
GNUNET_i2s (&s->target),
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr,
- s->addrlen),
+ plugin->protocol, s->address->address,
+ s->address->address_length),
*upload_data_size);
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
"Peer `%s' connection %p, GET on address `%s' disconnected\n",
GNUNET_i2s (&s->target), s->server_send,
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr, s->addrlen));
+ plugin->protocol, s->address->address,
+ s->address->address_length));
s->server_send = NULL;
- if (NULL != (s->server_recv))
+ if (!(sc->options & OPTION_LONG_POLL) && NULL != (s->server_recv))
{
- s->server_recv->disconnect = GNUNET_YES;
+ s->disconnect = GNUNET_YES;
GNUNET_assert (NULL != s->server_recv->mhd_conn);
#if MHD_VERSION >= 0x00090E00
MHD_set_connection_option (s->server_recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
"Peer `%s' connection %p PUT on address `%s' disconnected\n",
GNUNET_i2s (&s->target), s->server_recv,
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr, s->addrlen));
+ plugin->protocol, s->address->address,
+ s->address->address_length));
s->server_recv = NULL;
- /* Do not terminate session when PUT disconnects
- if (NULL != (s->server_send))
- {
- s->server_send->disconnect = GNUNET_YES;
- GNUNET_assert (NULL != s->server_send->mhd_conn);
-#if MHD_VERSION >= 0x00090E00
- MHD_set_connection_option (s->server_send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
- 1);
-#endif
- server_reschedule (plugin, s->server_send->mhd_daemon, GNUNET_NO);
- }*/
if (s->msg_tk != NULL)
{
GNUNET_SERVER_mst_destroy (s->msg_tk);
GNUNET_free (sc);
plugin->cur_connections--;
- if ((s->server_send == NULL) && (s->server_recv == NULL))
+ if (s->disconnect && (s->server_send == NULL) && (s->server_recv == NULL))
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Peer `%s' on address `%s' disconnected\n",
GNUNET_i2s (&s->target),
http_common_plugin_address_to_string (NULL,
- plugin->protocol,
- s->addr, s->addrlen));
+ plugin->protocol, s->address->address,
+ s->address->address_length));
if ((GNUNET_YES == s->session_passed) && (GNUNET_NO == s->session_ended))
{
/* Notify transport immediately that this session is invalid */
s->session_ended = GNUNET_YES;
- plugin->env->session_end (plugin->env->cls, &s->target, s);
+ plugin->env->session_end (plugin->env->cls, s->address, s);
}
server_delete_session (plugin, s);
}
"No usable TLS certificate found, creating certificate\n");
errno = 0;
cert_creation =
- GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+ GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+ NULL, NULL, NULL,
"gnunet-transport-certificate-creation",
"gnunet-transport-certificate-creation",
key_file, cert_file, NULL);
socklen_t addrlen)
{
struct HTTP_Server_Plugin *plugin = cls;
+ struct GNUNET_HELLO_Address *address;
struct HttpAddressWrapper *w = NULL;
w = GNUNET_new (struct HttpAddressWrapper);
http_common_plugin_address_to_string (NULL,
plugin->protocol,
w->address, w->addrlen));
+ /* modify our published address list */
#if BUILD_HTTPS
- plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "https_client");
+ address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "https_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE);
#else
- plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "http_client");
+ address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE);
#endif
+
+ plugin->env->notify_address (plugin->env->cls, add_remove, address);
+ GNUNET_HELLO_address_free (address);
}
socklen_t addrlen)
{
struct HTTP_Server_Plugin *plugin = cls;
+ struct GNUNET_HELLO_Address *address;
struct HttpAddressWrapper *w = plugin->addr_head;
size_t saddr_len;
void * saddr = http_common_address_from_socket (plugin->protocol, addr, addrlen);
http_common_plugin_address_to_string (NULL,
plugin->protocol,
w->address, w->addrlen));
+
+
GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
+
+ /* modify our published address list */
#if BUILD_HTTPS
- plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "https_client");
+ address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "https_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE);
#else
- plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "http_client");
+ address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE);
#endif
+ plugin->env->notify_address (plugin->env->cls, add_remove, address);
+ GNUNET_HELLO_address_free (address);
GNUNET_free (w->address);
GNUNET_free (w);
}
server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct HTTP_Server_Plugin *plugin = cls;
+ struct HttpAddress *ext_addr;
+ size_t ext_addr_len;
unsigned int urlen;
char *url;
GNUNET_asprintf(&url, "%s://%s", plugin->protocol, plugin->external_hostname);
urlen = strlen (url) + 1;
- plugin->ext_addr = GNUNET_malloc (sizeof (struct HttpAddress) + urlen);
- plugin->ext_addr->options = htonl(plugin->options);
- plugin->ext_addr->urlen = htonl (urlen);
- plugin->ext_addr_len = sizeof (struct HttpAddress) + urlen;
- memcpy (&plugin->ext_addr[1], url, urlen);
+ ext_addr = GNUNET_malloc (sizeof (struct HttpAddress) + urlen);
+ ext_addr->options = htonl(plugin->options);
+ ext_addr->urlen = htonl (urlen);
+ ext_addr_len = sizeof (struct HttpAddress) + urlen;
+ memcpy (&ext_addr[1], url, urlen);
GNUNET_free (url);
+
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Notifying transport about external hostname address `%s'\n", plugin->external_hostname);
#if BUILD_HTTPS
if (GNUNET_YES == plugin->verify_external_hostname)
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
- "Enabling SSL verification for external hostname address `%s'\n", plugin->external_hostname);
- plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
- plugin->ext_addr, plugin->ext_addr_len,
- "https_client");
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
+ "Enabling SSL verification for external hostname address `%s'\n",
+ plugin->external_hostname);
+ plugin->ext_addr = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "https_client", ext_addr, ext_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE );
+ plugin->env->notify_address (plugin->env->cls, GNUNET_YES, plugin->ext_addr);
+ GNUNET_free (ext_addr);
#else
- plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
- plugin->ext_addr, plugin->ext_addr_len,
- "http_client");
+ plugin->ext_addr = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
+ "http_client", ext_addr, ext_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE );
+ plugin->env->notify_address (plugin->env->cls, GNUNET_YES, plugin->ext_addr);
+ GNUNET_free (ext_addr);
#endif
}
"Notifying transport to remove address `%s'\n",
http_common_plugin_address_to_string (NULL,
plugin->protocol,
- plugin->ext_addr,
- plugin->ext_addr_len));
+ plugin->ext_addr->address,
+ plugin->ext_addr->address_length));
#if BUILD_HTTPS
plugin->env->notify_address (plugin->env->cls,
GNUNET_NO,
- plugin->ext_addr,
- plugin->ext_addr_len,
- "https_client");
+ plugin->ext_addr);
#else
plugin->env->notify_address (plugin->env->cls,
GNUNET_NO,
- plugin->ext_addr,
- plugin->ext_addr_len,
- "http_client");
+ plugin->ext_addr);
#endif
+ GNUNET_HELLO_address_free (plugin->ext_addr);
+ plugin->ext_addr = NULL;
}
/* Stop to report addresses to transport service */
{
/* Notify transport immediately that this session is invalid */
pos->session_ended = GNUNET_YES;
- plugin->env->session_end (plugin->env->cls, &pos->target, pos);
+ plugin->env->session_end (plugin->env->cls, pos->address, pos);
}
server_delete_session (plugin, pos);
}
GNUNET_free_non_null (plugin->ext_addr);
GNUNET_free_non_null (plugin->server_addr_v4);
GNUNET_free_non_null (plugin->server_addr_v6);
+ regfree(&plugin->url_regex);
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
_("Shutdown for plugin `%s' complete\n"),
/**
* Function obtain the network type for a session
*
- * @param cls closure ('struct Plugin*')
+ * @param cls closure ('struct HTTP_Server_Plugin*')
* @param session the session
* @return the network type in HBO or GNUNET_SYSERR
*/
plugin->protocol = "http";
#endif
+ /* Compile URL regex */
+ if (regcomp(&plugin->url_regex, URL_REGEX, REG_EXTENDED)) {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+ _("Unable to compile URL regex\n"));
+ LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+ return NULL;
+ }
+
/* Configure plugin */
if (GNUNET_SYSERR == server_configure_plugin (plugin))
{