diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-12-13 12:39:09 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-12-13 12:39:09 +0000 |
commit | 9ff68546aa6e7226e37e9231b3961ae72eb0cbb2 (patch) | |
tree | e389457d5da2b28e452fb12c0233d46d1fd8b219 /src/transport/plugin_transport_udp.c | |
parent | e803ed2a69a7a925d51c50334e79223284c00f5f (diff) | |
download | gnunet-9ff68546aa6e7226e37e9231b3961ae72eb0cbb2.tar.gz gnunet-9ff68546aa6e7226e37e9231b3961ae72eb0cbb2.zip |
-code cleanup, fixing #3207: timeout can be NULL in reschedule_session_timeout if we are 'in destroy', in which case we should simply do nothing
Diffstat (limited to 'src/transport/plugin_transport_udp.c')
-rw-r--r-- | src/transport/plugin_transport_udp.c | 170 |
1 files changed, 84 insertions, 86 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c index 99d4f9fb1..c85cbd885 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c | |||
@@ -193,8 +193,20 @@ struct Session | |||
193 | */ | 193 | */ |
194 | size_t addrlen; | 194 | size_t addrlen; |
195 | 195 | ||
196 | /** | ||
197 | * Reference counter to indicate that this session is | ||
198 | * currently being used and must not be destroyed; | ||
199 | * setting @e in_destroy will destroy it as soon as | ||
200 | * possible. | ||
201 | */ | ||
196 | unsigned int rc; | 202 | unsigned int rc; |
197 | 203 | ||
204 | /** | ||
205 | * Is this session about to be destroyed (sometimes we cannot | ||
206 | * destroy a session immediately as below us on the stack | ||
207 | * there might be code that still uses it; in this case, | ||
208 | * @e rc is non-zero). | ||
209 | */ | ||
198 | int in_destroy; | 210 | int in_destroy; |
199 | 211 | ||
200 | int inbound; | 212 | int inbound; |
@@ -479,25 +491,6 @@ udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
479 | 491 | ||
480 | 492 | ||
481 | /** | 493 | /** |
482 | * Cancel timeout | ||
483 | */ | ||
484 | static void | ||
485 | stop_session_timeout (struct Session *s) | ||
486 | { | ||
487 | GNUNET_assert (NULL != s); | ||
488 | |||
489 | if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) | ||
490 | { | ||
491 | GNUNET_SCHEDULER_cancel (s->timeout_task); | ||
492 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
493 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
494 | "Timeout stopped for session %p canceled\n", | ||
495 | s); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | |||
500 | /** | ||
501 | * (re)schedule select tasks for this plugin. | 494 | * (re)schedule select tasks for this plugin. |
502 | * | 495 | * |
503 | * @param plugin plugin to reschedule | 496 | * @param plugin plugin to reschedule |
@@ -713,19 +706,19 @@ udp_string_to_address (void *cls, const char *addr, uint16_t addrlen, | |||
713 | 706 | ||
714 | 707 | ||
715 | static void | 708 | static void |
716 | ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 709 | ppc_cancel_task (void *cls, |
710 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
717 | { | 711 | { |
718 | struct PrettyPrinterContext *ppc = cls; | 712 | struct PrettyPrinterContext *ppc = cls; |
719 | /* GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PPC %p was not removed!\n", ppc); */ | 713 | |
720 | ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 714 | ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
721 | if (NULL != ppc->resolver_handle) | 715 | if (NULL != ppc->resolver_handle) |
722 | { | 716 | { |
723 | GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); | 717 | GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); |
724 | ppc->resolver_handle = NULL; | 718 | ppc->resolver_handle = NULL; |
725 | } | 719 | } |
726 | 720 | GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); | |
727 | GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); | 721 | GNUNET_free (ppc); |
728 | GNUNET_free (ppc); | ||
729 | } | 722 | } |
730 | 723 | ||
731 | 724 | ||
@@ -741,7 +734,7 @@ append_port (void *cls, const char *hostname) | |||
741 | struct PrettyPrinterContext *ppc = cls; | 734 | struct PrettyPrinterContext *ppc = cls; |
742 | struct PrettyPrinterContext *cur; | 735 | struct PrettyPrinterContext *cur; |
743 | char *ret; | 736 | char *ret; |
744 | /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC callback: %p `%s'\n",ppc, hostname); */ | 737 | |
745 | if (hostname == NULL) | 738 | if (hostname == NULL) |
746 | { | 739 | { |
747 | ppc->asc (ppc->asc_cls, NULL); | 740 | ppc->asc (ppc->asc_cls, NULL); |
@@ -749,29 +742,40 @@ append_port (void *cls, const char *hostname) | |||
749 | GNUNET_SCHEDULER_cancel (ppc->timeout_task); | 742 | GNUNET_SCHEDULER_cancel (ppc->timeout_task); |
750 | ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 743 | ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
751 | ppc->resolver_handle = NULL; | 744 | ppc->resolver_handle = NULL; |
752 | /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was removed!\n", ppc); */ | ||
753 | GNUNET_free (ppc); | 745 | GNUNET_free (ppc); |
754 | return; | 746 | return; |
755 | } | 747 | } |
756 | for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) | 748 | for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) |
757 | { | 749 | { |
758 | if (cur == ppc) | 750 | if (cur == ppc) |
759 | break; | 751 | break; |
760 | } | 752 | } |
761 | if (NULL == cur) | 753 | if (NULL == cur) |
762 | { | 754 | { |
763 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid callback for PPC %p \n", ppc); | 755 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
764 | return; | 756 | "Invalid callback for PPC %p \n", ppc); |
757 | return; | ||
765 | } | 758 | } |
766 | 759 | ||
767 | if (GNUNET_YES == ppc->ipv6) | 760 | if (GNUNET_YES == ppc->ipv6) |
768 | GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); | 761 | GNUNET_asprintf (&ret, |
762 | "%s.%u.[%s]:%d", | ||
763 | PLUGIN_NAME, | ||
764 | ppc->options, | ||
765 | hostname, | ||
766 | ppc->port); | ||
769 | else | 767 | else |
770 | GNUNET_asprintf (&ret, "%s.%u.%s:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); | 768 | GNUNET_asprintf (&ret, |
769 | "%s.%u.%s:%d", | ||
770 | PLUGIN_NAME, | ||
771 | ppc->options, | ||
772 | hostname, | ||
773 | ppc->port); | ||
771 | ppc->asc (ppc->asc_cls, ret); | 774 | ppc->asc (ppc->asc_cls, ret); |
772 | GNUNET_free (ret); | 775 | GNUNET_free (ret); |
773 | } | 776 | } |
774 | 777 | ||
778 | |||
775 | /** | 779 | /** |
776 | * Convert the transports address to a nice, human-readable | 780 | * Convert the transports address to a nice, human-readable |
777 | * format. | 781 | * format. |
@@ -841,7 +845,7 @@ udp_plugin_address_pretty_printer (void *cls, const char *type, | |||
841 | asc (asc_cls, NULL); | 845 | asc (asc_cls, NULL); |
842 | return; | 846 | return; |
843 | } | 847 | } |
844 | ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext)); | 848 | ppc = GNUNET_new (struct PrettyPrinterContext); |
845 | ppc->asc = asc; | 849 | ppc->asc = asc; |
846 | ppc->asc_cls = asc_cls; | 850 | ppc->asc_cls = asc_cls; |
847 | ppc->port = port; | 851 | ppc->port = port; |
@@ -853,9 +857,10 @@ udp_plugin_address_pretty_printer (void *cls, const char *type, | |||
853 | ppc->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(timeout, 2), | 857 | ppc->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(timeout, 2), |
854 | &ppc_cancel_task, ppc); | 858 | &ppc_cancel_task, ppc); |
855 | GNUNET_CONTAINER_DLL_insert (ppc_dll_head, ppc_dll_tail, ppc); | 859 | GNUNET_CONTAINER_DLL_insert (ppc_dll_head, ppc_dll_tail, ppc); |
856 | /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was created!\n", ppc); */ | 860 | ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, |
857 | ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); | 861 | !numeric, |
858 | 862 | timeout, | |
863 | &append_port, ppc); | ||
859 | } | 864 | } |
860 | 865 | ||
861 | 866 | ||
@@ -1104,7 +1109,7 @@ udp_plugin_check_address (void *cls, const void *addr, size_t addrlen) | |||
1104 | 1109 | ||
1105 | 1110 | ||
1106 | /** | 1111 | /** |
1107 | * Task to free resources associated with a session. | 1112 | * Function to free last resources associated with a session. |
1108 | * | 1113 | * |
1109 | * @param s session to free | 1114 | * @param s session to free |
1110 | */ | 1115 | */ |
@@ -1113,7 +1118,7 @@ free_session (struct Session *s) | |||
1113 | { | 1118 | { |
1114 | if (NULL != s->frag_ctx) | 1119 | if (NULL != s->frag_ctx) |
1115 | { | 1120 | { |
1116 | GNUNET_FRAGMENT_context_destroy(s->frag_ctx->frag, NULL, NULL); | 1121 | GNUNET_FRAGMENT_context_destroy (s->frag_ctx->frag, NULL, NULL); |
1117 | GNUNET_free (s->frag_ctx); | 1122 | GNUNET_free (s->frag_ctx); |
1118 | s->frag_ctx = NULL; | 1123 | s->frag_ctx = NULL; |
1119 | } | 1124 | } |
@@ -1235,8 +1240,12 @@ udp_disconnect_session (void *cls, | |||
1235 | s, | 1240 | s, |
1236 | GNUNET_i2s (&s->target), | 1241 | GNUNET_i2s (&s->target), |
1237 | GNUNET_a2s (s->sock_addr, s->addrlen)); | 1242 | GNUNET_a2s (s->sock_addr, s->addrlen)); |
1238 | stop_session_timeout (s); | 1243 | /* stop timeout task */ |
1239 | 1244 | if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) | |
1245 | { | ||
1246 | GNUNET_SCHEDULER_cancel (s->timeout_task); | ||
1247 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1248 | } | ||
1240 | if (NULL != s->frag_ctx) | 1249 | if (NULL != s->frag_ctx) |
1241 | { | 1250 | { |
1242 | /* Remove fragmented message due to disconnect */ | 1251 | /* Remove fragmented message due to disconnect */ |
@@ -1340,6 +1349,9 @@ udp_disconnect (void *cls, | |||
1340 | 1349 | ||
1341 | /** | 1350 | /** |
1342 | * Session was idle, so disconnect it | 1351 | * Session was idle, so disconnect it |
1352 | * | ||
1353 | * @param cls the `struct Session` to time out | ||
1354 | * @param tc scheduler context | ||
1343 | */ | 1355 | */ |
1344 | static void | 1356 | static void |
1345 | session_timeout (void *cls, | 1357 | session_timeout (void *cls, |
@@ -1360,42 +1372,23 @@ session_timeout (void *cls, | |||
1360 | 1372 | ||
1361 | 1373 | ||
1362 | /** | 1374 | /** |
1363 | * Start session timeout | ||
1364 | */ | ||
1365 | static void | ||
1366 | start_session_timeout (struct Session *s) | ||
1367 | { | ||
1368 | GNUNET_assert (NULL != s); | ||
1369 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task); | ||
1370 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, | ||
1371 | &session_timeout, | ||
1372 | s); | ||
1373 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1374 | "Timeout for session %p set to %s\n", | ||
1375 | s, | ||
1376 | GNUNET_STRINGS_relative_time_to_string (UDP_SESSION_TIME_OUT, | ||
1377 | GNUNET_YES)); | ||
1378 | } | ||
1379 | |||
1380 | |||
1381 | /** | ||
1382 | * Increment session timeout due to activity | 1375 | * Increment session timeout due to activity |
1376 | * | ||
1377 | * @param s session to reschedule timeout activity for | ||
1383 | */ | 1378 | */ |
1384 | static void | 1379 | static void |
1385 | reschedule_session_timeout (struct Session *s) | 1380 | reschedule_session_timeout (struct Session *s) |
1386 | { | 1381 | { |
1387 | GNUNET_assert (NULL != s); | 1382 | if (GNUNET_YES == s->in_destroy) |
1383 | return; | ||
1388 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); | 1384 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); |
1389 | |||
1390 | GNUNET_SCHEDULER_cancel (s->timeout_task); | 1385 | GNUNET_SCHEDULER_cancel (s->timeout_task); |
1391 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, | 1386 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, |
1392 | &session_timeout, | 1387 | &session_timeout, |
1393 | s); | 1388 | s); |
1394 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1389 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1395 | "Timeout rescheduled for session %p set to %s\n", | 1390 | "Timeout restarted for session %p\n", |
1396 | s, | 1391 | s); |
1397 | GNUNET_STRINGS_relative_time_to_string (UDP_SESSION_TIME_OUT, | ||
1398 | GNUNET_YES)); | ||
1399 | } | 1392 | } |
1400 | 1393 | ||
1401 | 1394 | ||
@@ -1480,7 +1473,9 @@ create_session (struct Plugin *plugin, | |||
1480 | s->flow_delay_from_other_peer = GNUNET_TIME_UNIT_ZERO_ABS; | 1473 | s->flow_delay_from_other_peer = GNUNET_TIME_UNIT_ZERO_ABS; |
1481 | s->flow_delay_for_other_peer = GNUNET_TIME_UNIT_ZERO; | 1474 | s->flow_delay_for_other_peer = GNUNET_TIME_UNIT_ZERO; |
1482 | s->inbound = GNUNET_NO; | 1475 | s->inbound = GNUNET_NO; |
1483 | start_session_timeout (s); | 1476 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, |
1477 | &session_timeout, | ||
1478 | s); | ||
1484 | return s; | 1479 | return s; |
1485 | } | 1480 | } |
1486 | 1481 | ||
@@ -1988,18 +1983,18 @@ process_inbound_tokenized_messages (void *cls, void *client, | |||
1988 | &si->sender, | 1983 | &si->sender, |
1989 | hdr, | 1984 | hdr, |
1990 | si->session, | 1985 | si->session, |
1991 | (GNUNET_YES == si->session->inbound) ? NULL : si->arg, | 1986 | (GNUNET_YES == si->session->inbound) |
1992 | (GNUNET_YES == si->session->inbound) ? 0 : si->args); | 1987 | ? NULL : si->arg, |
1993 | 1988 | (GNUNET_YES == si->session->inbound) | |
1989 | ? 0 : si->args); | ||
1994 | plugin->env->update_address_metrics (plugin->env->cls, | 1990 | plugin->env->update_address_metrics (plugin->env->cls, |
1995 | &si->sender, | 1991 | &si->sender, |
1996 | (GNUNET_YES == si->session->inbound) ? NULL : si->arg, | 1992 | (GNUNET_YES == si->session->inbound) ? NULL : si->arg, |
1997 | (GNUNET_YES == si->session->inbound) ? 0 : si->args, | 1993 | (GNUNET_YES == si->session->inbound) ? 0 : si->args, |
1998 | si->session, | 1994 | si->session, |
1999 | &si->session->ats, 1); | 1995 | &si->session->ats, 1); |
2000 | |||
2001 | si->session->flow_delay_for_other_peer = delay; | 1996 | si->session->flow_delay_for_other_peer = delay; |
2002 | reschedule_session_timeout(si->session); | 1997 | reschedule_session_timeout (si->session); |
2003 | return GNUNET_OK; | 1998 | return GNUNET_OK; |
2004 | } | 1999 | } |
2005 | 2000 | ||
@@ -2081,9 +2076,12 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg, | |||
2081 | si.arg = arg; | 2076 | si.arg = arg; |
2082 | si.args = args; | 2077 | si.args = args; |
2083 | s->rc++; | 2078 | s->rc++; |
2084 | GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1], | 2079 | GNUNET_SERVER_mst_receive (plugin->mst, |
2085 | ntohs (msg->header.size) - | 2080 | &si, |
2086 | sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO); | 2081 | (const char *) &msg[1], |
2082 | ntohs (msg->header.size) - sizeof (struct UDPMessage), | ||
2083 | GNUNET_YES, | ||
2084 | GNUNET_NO); | ||
2087 | s->rc--; | 2085 | s->rc--; |
2088 | if ( (0 == s->rc) && (GNUNET_YES == s->in_destroy)) | 2086 | if ( (0 == s->rc) && (GNUNET_YES == s->in_destroy)) |
2089 | free_session (s); | 2087 | free_session (s); |