From 063adb71c2a42c2733e0665caefabf1dd3e74844 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Fri, 16 Sep 2011 12:38:26 +0000 Subject: --- src/transport/plugin_transport_http.h | 10 +- src/transport/plugin_transport_http_client.c | 67 ++++++----- src/transport/plugin_transport_http_new.c | 7 +- src/transport/plugin_transport_http_server.c | 161 ++++++++++++++++++++++++--- 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); -- cgit v1.2.3