From f42ded3716ac792efe84e05cc6f1d5d5d8523e69 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Tue, 10 Jul 2012 13:35:28 +0000 Subject: [PATCH] - improving client disconnect code to fix mantis 2486 --- src/transport/plugin_transport_http.c | 123 +++++++++---------- src/transport/plugin_transport_http_client.c | 27 ++-- 2 files changed, 68 insertions(+), 82 deletions(-) diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c index 9b23be168..b3c463382 100644 --- a/src/transport/plugin_transport_http.c +++ b/src/transport/plugin_transport_http.c @@ -585,12 +585,34 @@ exist_session (struct Plugin *plugin, struct Session *s) return GNUNET_NO; } +/** + * Deleting the session + * Must not be used afterwards + */ void delete_session (struct Session *s) { + struct Plugin *plugin = s->plugin; stop_session_timeout(s); + GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); + struct HTTP_Message *msg = s->msg_head; + struct HTTP_Message *tmp = NULL; + + while (msg != NULL) + { + tmp = msg->next; + + GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); + if (msg->transmit_cont != NULL) + { + msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR); + } + GNUNET_free (msg); + msg = tmp; + } + if (s->msg_tk != NULL) { GNUNET_SERVER_mst_destroy (s->msg_tk); @@ -669,11 +691,12 @@ notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, { struct Plugin *plugin = cls; - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, - "Notifying transport about ending session %p\n"); + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, + "Notifying transport about ending session %p (`%s')\n", + s, + http_plugin_address_to_string(NULL, s->addr,s->addrlen)); plugin->env->session_end (plugin->env->cls, peer, s); - GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); delete_session (s); } @@ -845,7 +868,7 @@ http_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) struct Session *next = NULL; struct Session *s = plugin->head; - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Transport tells me to disconnect `%s'\n", GNUNET_i2s (target)); while (s != NULL) @@ -853,29 +876,15 @@ http_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) next = s->next; if (0 == memcmp (target, &s->target, sizeof (struct GNUNET_PeerIdentity))) { + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, + "Disconnecting %s session %p to `%s'\n", + (s->inbound == GNUNET_NO) ? "outbound" : "inbound", + s, GNUNET_i2s (target)); + if (s->inbound == GNUNET_NO) GNUNET_assert (GNUNET_OK == client_disconnect (s)); else GNUNET_assert (GNUNET_OK == server_disconnect (s)); - GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); - - struct HTTP_Message *msg = s->msg_head; - struct HTTP_Message *tmp = NULL; - - while (msg != NULL) - { - tmp = msg->next; - - GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); - if (msg->transmit_cont != NULL) - { - msg->transmit_cont (msg->transmit_cont_cls, target, GNUNET_SYSERR); - } - GNUNET_free (msg); - msg = tmp; - } - - delete_session (s); } s = next; } @@ -1326,10 +1335,6 @@ start_report_addresses (struct Plugin *plugin) while (res > 0) { res--; -#if 0 - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _("FREEING %s\n"), - GNUNET_a2s (addrs[res], addrlens[res])); -#endif GNUNET_assert (addrs[res] != NULL); GNUNET_free (addrs[res]); } @@ -1500,6 +1505,16 @@ fail: return res; } +#define TESTING GNUNET_NO + +#if TESTING +#define TIMEOUT_LOG GNUNET_ERROR_TYPE_ERROR +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) +#else +#define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG +#define TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT +#endif + /** * Session was idle, so disconnect it @@ -1511,9 +1526,9 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (TIMEOUT_LOG, "Session %p was idle for %llu ms, disconnecting\n", - s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); + s, (unsigned long long) TIMEOUT.rel_value); /* call session destroy function */ if (s->inbound == GNUNET_NO) @@ -1531,12 +1546,12 @@ start_session_timeout (struct Session *s) { GNUNET_assert (NULL != s); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task); - s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &session_timeout, s); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (TIMEOUT_LOG, "Timeout for session %p set to %llu ms\n", - s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); + s, (unsigned long long) TIMEOUT.rel_value); } @@ -1550,12 +1565,12 @@ reschedule_session_timeout (struct Session *s) GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); - s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &session_timeout, s); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (TIMEOUT_LOG, "Timeout rescheduled for session %p set to %llu ms\n", - s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); + s, (unsigned long long) TIMEOUT.rel_value); } @@ -1571,9 +1586,9 @@ stop_session_timeout (struct Session *s) { GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Timeout stopped for session %p canceled\n", - s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); + GNUNET_log (TIMEOUT_LOG, + "Timeout stopped for session %p\n", + s); } } @@ -1680,6 +1695,7 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct Session *s; + struct Session *next; if (NULL == plugin) { @@ -1694,13 +1710,14 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) s = plugin->head; while (s != NULL) { + next = s->next; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Disconnecting `%s' \n", GNUNET_i2s (&s->target)); if (s->inbound == GNUNET_NO) GNUNET_assert (GNUNET_OK == client_disconnect (s)); else GNUNET_assert (GNUNET_OK == server_disconnect (s)); - s = s->next; + s = next; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Stopping server\n"); @@ -1711,34 +1728,6 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) /* Stop client */ client_stop (plugin); - /* deleting up sessions */ - s = plugin->head; - while (s != NULL) - { - struct Session *t = s->next; - - GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); - - struct HTTP_Message *msg = s->msg_head; - struct HTTP_Message *tmp = NULL; - - while (msg != NULL) - { - tmp = msg->next; - - GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); - if (msg->transmit_cont != NULL) - { - msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR); - } - GNUNET_free (msg); - msg = tmp; - } - - delete_session (s); - s = t; - } - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Plugin `%s' unloaded\n", plugin->name); GNUNET_free_non_null (plugin->server_addr_v4); diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c index 6355bb4e5..ff23da974 100644 --- a/src/transport/plugin_transport_http_client.c +++ b/src/transport/plugin_transport_http_client.c @@ -200,10 +200,9 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct Session *s = NULL; char *d = (char *) s; - - //GNUNET_assert (easy_h != NULL); if (easy_h == NULL) { + GNUNET_break (0); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: connection to ended with reason %i: `%s', %i handles running\n", msg->data.result, @@ -222,7 +221,6 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } GNUNET_assert (s != NULL); - if (msg->msg == CURLMSG_DONE) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, @@ -233,13 +231,8 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) msg->data.result, curl_easy_strerror (msg->data.result)); + /* Disconnect other transmission direction and tell transport */ client_disconnect (s); - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, - plugin->name, - "Notifying about ended session to peer `%s' `%s'\n", - GNUNET_i2s (&s->target), - http_plugin_address_to_string (plugin, s->addr, s->addrlen)); - notify_session_end (plugin, &s->target, s); } } } @@ -266,13 +259,14 @@ client_disconnect (struct Session *s) if (s->client_put != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, - "Client: %p Deleting outbound PUT session to peer `%s'\n", - s->client_put, GNUNET_i2s (&s->target)); + "Client: %p / %p Deleting outbound PUT session to peer `%s'\n", + s, s->client_put, GNUNET_i2s (&s->target)); + /* remove curl handle from multi handle */ mret = curl_multi_remove_handle (plugin->client_mh, s->client_put); if (mret != CURLM_OK) { - curl_easy_cleanup (s->client_put); + /* clean up easy handle, handle is now invalid and free'd */ res = GNUNET_SYSERR; GNUNET_break (0); } @@ -290,13 +284,15 @@ client_disconnect (struct Session *s) if (s->client_get != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, - "Client: %p Deleting outbound GET session to peer `%s'\n", + "Client: %p / %p Deleting outbound GET session to peer `%s'\n", + s, s->client_get, GNUNET_i2s (&s->target)); + /* remove curl handle from multi handle */ mret = curl_multi_remove_handle (plugin->client_mh, s->client_get); if (mret != CURLM_OK) { - curl_easy_cleanup (s->client_get); + /* clean up easy handle, handle is now invalid and free'd */ res = GNUNET_SYSERR; GNUNET_break (0); } @@ -317,6 +313,8 @@ client_disconnect (struct Session *s) plugin->cur_connections -= 2; + notify_session_end (plugin, &s->target, s); + GNUNET_assert (plugin->outbound_sessions > 0); plugin->outbound_sessions --; GNUNET_STATISTICS_set (plugin->env->stats, @@ -330,7 +328,6 @@ client_disconnect (struct Session *s) GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } - client_schedule (plugin, GNUNET_YES); return res; -- 2.25.1