summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2011-09-16 12:38:26 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2011-09-16 12:38:26 +0000
commit063adb71c2a42c2733e0665caefabf1dd3e74844 (patch)
treeb7454d6f1b0e425a29ec6a8459386e8e69e1e670
parent29fa14da9469c471234a09250cde179ec95066d3 (diff)
-rw-r--r--src/transport/plugin_transport_http.h10
-rw-r--r--src/transport/plugin_transport_http_client.c67
-rw-r--r--src/transport/plugin_transport_http_new.c7
-rw-r--r--src/transport/plugin_transport_http_server.c161
4 files changed, 200 insertions, 45 deletions
diff --git a/src/transport/plugin_transport_http.h b/src/transport/plugin_transport_http.h
index 8ea1b03cf..11b369d40 100644
--- a/src/transport/plugin_transport_http.h
+++ b/src/transport/plugin_transport_http.h
@@ -54,6 +54,9 @@
#define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_done
#endif
+#define INBOUND GNUNET_YES
+#define OUTBOUND GNUNET_NO
+
#define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
@@ -227,13 +230,16 @@ struct Session
void *client_put;
void *client_get;
- void *server_put;
- void *server_get;
+ void *server_recv;
+ void *server_send;
uint32_t tag;
};
+void
+delete_session (struct Session *s);
+
struct Session *
create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
const void *addr, size_t addrlen,
diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c
index ca582332a..f62f7b2dd 100644
--- a/src/transport/plugin_transport_http_client.c
+++ b/src/transport/plugin_transport_http_client.c
@@ -126,6 +126,7 @@ client_schedule (struct Plugin *plugin)
gws = GNUNET_NETWORK_fdset_create ();
GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+
plugin->client_perform_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
GNUNET_SCHEDULER_NO_TASK,
@@ -179,10 +180,10 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Connection to '%s' %s ended\n", GNUNET_i2s(&s->target), http_plugin_address_to_string(s->plugin, s->addr, s->addrlen));
+ "Connection to '%s' %s ended\n", GNUNET_i2s(&s->target), http_plugin_address_to_string(plugin, s->addr, s->addrlen));
#endif
client_disconnect(s);
- notify_session_end (s->plugin, &s->target, s);
+ notify_session_end (plugin, &s->target, s);
}
}
@@ -197,7 +198,7 @@ client_disconnect (struct Session *s)
{
int res = GNUNET_OK;
CURLMcode mret;
- struct Plugin *plugin = s->plugin;
+ struct Plugin *plugin = plugin;
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
@@ -205,14 +206,18 @@ client_disconnect (struct Session *s)
GNUNET_i2s (&s->target));
#endif
- mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
- if (mret != CURLM_OK)
+ if (s->client_put != NULL)
{
+ mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
+ if (mret != CURLM_OK)
+ {
+ curl_easy_cleanup (s->client_put);
+ res = GNUNET_SYSERR;
+ GNUNET_break (0);
+ }
curl_easy_cleanup (s->client_put);
- res = GNUNET_SYSERR;
- GNUNET_break (0);
+ s->client_put = NULL;
}
- curl_easy_cleanup (s->client_put);
#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
@@ -220,15 +225,20 @@ client_disconnect (struct Session *s)
GNUNET_i2s (&s->target));
#endif
- mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
- if (mret != CURLM_OK)
+ if (s->client_get != NULL)
{
+ mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
+ if (mret != CURLM_OK)
+ {
+ curl_easy_cleanup (s->client_get);
+ res = GNUNET_SYSERR;
+ GNUNET_break (0);
+ }
curl_easy_cleanup (s->client_get);
- res = GNUNET_SYSERR;
- GNUNET_break (0);
+ s->client_get = NULL;
}
- curl_easy_cleanup (s->client_get);
- plugin->cur_connections += 2;
+
+ plugin->cur_connections -= 2;
/* Re-schedule since handles have changed */
if (plugin->client_perform_task!= GNUNET_SCHEDULER_NO_TASK)
@@ -236,7 +246,6 @@ client_disconnect (struct Session *s)
GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
}
-
plugin->client_perform_task = GNUNET_SCHEDULER_add_now(client_run, plugin);
return res;
@@ -246,23 +255,24 @@ client_disconnect (struct Session *s)
int
client_connect (struct Session *s)
{
+ struct Plugin *plugin = s->plugin;
int res = GNUNET_OK;
char *url;
CURLMcode mret;
-#if DEBUG_HTTP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+#if VERBOSE_CLIENT
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Initiating outbound session peer `%s'\n",
GNUNET_i2s (&s->target));
#endif
s->inbound = GNUNET_NO;
- s->plugin->last_tag++;
+ plugin->last_tag++;
/* create url */
- GNUNET_asprintf (&url, "%s%s;%u", http_plugin_address_to_string (s->plugin, s->addr, s->addrlen), GNUNET_h2s_full (&s->plugin->env->my_identity->hashPubKey),s->plugin->last_tag);
+ GNUNET_asprintf (&url, "%s%s;%u", http_plugin_address_to_string (plugin, s->addr, s->addrlen), GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey),plugin->last_tag);
#if 0
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"URL `%s'\n",
url);
#endif
@@ -329,7 +339,7 @@ client_connect (struct Session *s)
GNUNET_free (url);
- mret = curl_multi_add_handle (s->plugin->client_mh, s->client_get);
+ mret = curl_multi_add_handle (plugin->client_mh, s->client_get);
if (mret != CURLM_OK)
{
curl_easy_cleanup (s->client_get);
@@ -337,10 +347,10 @@ client_connect (struct Session *s)
GNUNET_break (0);
}
- mret = curl_multi_add_handle (s->plugin->client_mh, s->client_put);
+ mret = curl_multi_add_handle (plugin->client_mh, s->client_put);
if (mret != CURLM_OK)
{
- curl_multi_remove_handle (s->plugin->client_mh, s->client_get);
+ curl_multi_remove_handle (plugin->client_mh, s->client_get);
curl_easy_cleanup (s->client_get);
curl_easy_cleanup (s->client_put);
res = GNUNET_SYSERR;
@@ -348,8 +358,15 @@ client_connect (struct Session *s)
}
/* Perform connect */
- s->plugin->cur_connections += 2;
- s->plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, s->plugin);
+ plugin->cur_connections += 2;
+
+ /* Re-schedule since handles have changed */
+ if (plugin->client_perform_task!= GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
+ plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin);
return res;
}
diff --git a/src/transport/plugin_transport_http_new.c b/src/transport/plugin_transport_http_new.c
index 37fae8972..17b2879f6 100644
--- a/src/transport/plugin_transport_http_new.c
+++ b/src/transport/plugin_transport_http_new.c
@@ -404,6 +404,8 @@ void
delete_session (struct Session *s)
{
GNUNET_free (s->addr);
+ GNUNET_free_non_null(s->server_recv);
+ GNUNET_free_non_null(s->server_send);
GNUNET_free (s);
}
@@ -972,7 +974,10 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
while (s != NULL)
{
struct Session *t = s->next;
-
+#if DEBUG_HTTP
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Disconnecting `%s' \n", GNUNET_i2s (&s->target));
+#endif
if (s->inbound == GNUNET_NO)
GNUNET_assert (GNUNET_OK == client_disconnect (s));
else
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index eec8939c7..df164aa4b 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -40,6 +40,18 @@ server_log (void *arg, const char *fmt, va_list ap)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "server: %s\n", text);
}
+struct ServerConnection
+{
+ /* _RECV or _SEND */
+ int direction;
+
+ /* should this connection get disconnected? GNUNET_YES/NO */
+ int disconnect;
+
+ struct Session *session;
+ struct MHD_Connection * mhd_conn;
+};
+
/**
* Check if incoming connection is accepted.
* NOTE: Here every connection is accepted
@@ -233,15 +245,16 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
void **httpSessionCache)
{
struct Plugin *plugin = cls;
- struct Session *s = *httpSessionCache;
+ struct ServerConnection *sc = *httpSessionCache;
+ struct Session *s = NULL;
+
int res = MHD_YES;
struct MHD_Response *response;
GNUNET_assert (cls != NULL);
/* new connection */
- if (s == NULL)
- {
-
+ if (sc == NULL)
+ {
uint32_t tag;
const union MHD_ConnectionInfo *conn_info;
size_t addrlen;
@@ -319,7 +332,11 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
if (t == NULL)
goto create;
- if ((direction == _SEND) && (t->server_get != NULL))
+#if VERBOSE_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Found existing semi-session for `%s'\n", GNUNET_i2s (&target));
+#endif
+
+ if ((direction == _SEND) && (t->server_send != NULL))
{
#if VERBOSE_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Duplicate GET session, dismissing new connection from peer `%s'\n", GNUNET_i2s (&target));
@@ -329,7 +346,6 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
else
{
s = t;
- s->server_get = s;
GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
#if VERBOSE_SERVER
@@ -338,7 +354,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
goto found;
}
- if ((direction == _RECEIVE) && (t->server_put != NULL))
+ if ((direction == _RECEIVE) && (t->server_recv != NULL))
{
#if VERBOSE_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "server: Duplicate PUT session, dismissing new connection from peer `%s'\n", GNUNET_i2s (&target));
@@ -348,7 +364,6 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
else
{
s = t;
- s->server_put = s;
GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
#if VERBOSE_SERVER
@@ -373,9 +388,9 @@ create:
s->inbound = GNUNET_YES;
s->tag= tag;
if (0 == strcmp (MHD_HTTP_METHOD_PUT, method))
- s->server_put = s;
+ s->server_recv = s;
if (0 == strcmp (MHD_HTTP_METHOD_GET, method))
- s->server_get = s;
+ s->server_send = s;
GNUNET_CONTAINER_DLL_insert (plugin->server_semi_head, plugin->server_semi_tail, s);
goto found;
@@ -388,11 +403,36 @@ error:
found:
- (*httpSessionCache) = s;
- return MHD_YES;
+
+ sc = GNUNET_malloc (sizeof (struct ServerConnection));
+ sc->mhd_conn = mhd_connection;
+ sc->direction = direction;
+ sc->session = s;
+ if (direction == _SEND)
+ s->server_send = sc;
+ if (direction == _RECEIVE)
+ s->server_recv = sc;
+
+ (*httpSessionCache) = sc;
+ return MHD_YES;
}
+ /* existing connection */
+ sc = (*httpSessionCache);
+ s = sc->session;
+ /* connection is to be disconnected*/
+ if (sc->disconnect == GNUNET_YES)
+ {
+ response = MHD_create_response_from_data (strlen ("Thank you!"), "Thank you!", MHD_NO, MHD_NO);
+ res = MHD_queue_response (mhd_connection, MHD_HTTP_OK, response);
+#if VERBOSE_SERVER
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sent HTTP/1.1: 200 OK as PUT Response\n");
+#endif
+ MHD_destroy_response (response);
+ return MHD_YES;
+ }
return res;
}
@@ -401,20 +441,95 @@ static void
server_disconnect_cb (void *cls, struct MHD_Connection *connection,
void **httpSessionCache)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "server: server_disconnect_cb\n");
- /*
- struct Session *s = *httpSessionCache;
+ struct ServerConnection *sc = *httpSessionCache;
+ struct ServerConnection *tc = *httpSessionCache;
+ struct Session * s = NULL;
+ struct Session * t = NULL;
+ struct Plugin * plugin = NULL;
- if (s != NULL)
+ if (sc == NULL)
+ return;
+
+ s = sc->session;
+ plugin = s-> plugin;
+ if (sc->direction == _SEND)
+ {
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' PUT on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
+ s->server_send = NULL;
+ /* FIXME miminimize timeout here */
+ if (s->server_recv != NULL)
+ {
+ tc = s->server_recv;
+ tc->disconnect = GNUNET_YES;
+ }
+ }
+ if (sc->direction == _RECEIVE)
{
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' GET on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
+ s->server_recv = NULL;
+ //MHD_
+ if (s->server_send != NULL)
+ {
+ tc = s->server_send;
+ tc->disconnect = GNUNET_YES;
+ }
+ }
+ GNUNET_free (sc);
+
+ t = plugin->server_semi_head;
+ while (t != NULL)
+ {
+ if (t == s)
+ {
+ GNUNET_CONTAINER_DLL_remove(plugin->server_semi_head, plugin->server_semi_tail, s);
+ GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, s);
+ break;
+ }
+ t = t->next;
+ }
+
+ if ((s->server_send == NULL) && (s->server_recv == NULL))
+ {
+#if VERBOSE_SERVER
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Server: peer `%s' on address `%s' disconnected\n",
+ GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen));
+#endif
notify_session_end(s->plugin, &s->target, s);
}
-*/
}
int
server_disconnect (struct Session *s)
{
+ struct Plugin *plugin = s->plugin;
+ struct Session *t = plugin->head;
+
+ while (t != NULL)
+ {
+ if (t->inbound == GNUNET_YES)
+ {
+ if (t->server_send != NULL)
+ {
+ ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
+ }
+ if (t->server_send != NULL)
+ {
+ ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
+ }
+ }
+ t = t->next;
+ }
+
+
return GNUNET_OK;
}
@@ -659,6 +774,9 @@ server_start (struct Plugin *plugin)
void
server_stop (struct Plugin *plugin)
{
+ struct Session *s = NULL;
+ struct Session *t = NULL;
+
if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
@@ -682,6 +800,15 @@ server_stop (struct Plugin *plugin)
plugin->server_v6 = NULL;
}
+ /* cleaning up semi-sessions never propagated */
+ s = plugin->server_semi_head;
+ while (s != NULL)
+ {
+ t = s->next;
+ delete_session (s);
+ s = t;
+ }
+
#if BUILD_HTTPS
GNUNET_free_non_null (plugin->crypto_init);
GNUNET_free_non_null (plugin->cert);