diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-03-02 15:39:47 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-03-02 15:39:47 +0000 |
commit | d81a110b209d98e5db18fbd5d9516bec37138d4f (patch) | |
tree | 71c39e770cd1f15738c1d859b98bf5781f899cf6 /src/transport/plugin_transport_tcp.c | |
parent | a4d2d006ed644cd965d7d80f8e4c4ad4988fc972 (diff) | |
download | gnunet-d81a110b209d98e5db18fbd5d9516bec37138d4f.tar.gz gnunet-d81a110b209d98e5db18fbd5d9516bec37138d4f.zip |
fix for mantis 2189
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 104 |
1 files changed, 50 insertions, 54 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index ff4b29451..52efd4d4e 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -43,6 +43,14 @@ | |||
43 | 43 | ||
44 | #define DEBUG_TCP_NAT GNUNET_EXTRA_LOGGING | 44 | #define DEBUG_TCP_NAT GNUNET_EXTRA_LOGGING |
45 | 45 | ||
46 | |||
47 | /** | ||
48 | * How long until we give up on establishing an NAT connection? | ||
49 | * Must be > 4 RTT | ||
50 | */ | ||
51 | #define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
52 | |||
53 | |||
46 | GNUNET_NETWORK_STRUCT_BEGIN | 54 | GNUNET_NETWORK_STRUCT_BEGIN |
47 | 55 | ||
48 | /** | 56 | /** |
@@ -240,6 +248,11 @@ struct Session | |||
240 | struct GNUNET_SERVER_Client *client; | 248 | struct GNUNET_SERVER_Client *client; |
241 | 249 | ||
242 | /** | 250 | /** |
251 | * Task cleaning up a NAT client connection establishment attempt; | ||
252 | */ | ||
253 | GNUNET_SCHEDULER_TaskIdentifier nat_connection_timeout; | ||
254 | |||
255 | /** | ||
243 | * Messages currently pending for transmission | 256 | * Messages currently pending for transmission |
244 | * to this peer, if any. | 257 | * to this peer, if any. |
245 | */ | 258 | */ |
@@ -807,7 +820,8 @@ disconnect_session (struct Session *session) | |||
807 | GNUNET_i2s (&session->target), | 820 | GNUNET_i2s (&session->target), |
808 | tcp_address_to_string(NULL, session->addr, session->addrlen)); | 821 | tcp_address_to_string(NULL, session->addr, session->addrlen)); |
809 | 822 | ||
810 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(plugin->sessionmap, &session->target.hashPubKey, session)); | 823 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(plugin->sessionmap, &session->target.hashPubKey, session) || |
824 | GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(plugin->nat_wait_conns, &session->target.hashPubKey, session)); | ||
811 | 825 | ||
812 | /* clean up state */ | 826 | /* clean up state */ |
813 | if (session->transmit_handle != NULL) | 827 | if (session->transmit_handle != NULL) |
@@ -817,6 +831,13 @@ disconnect_session (struct Session *session) | |||
817 | } | 831 | } |
818 | session->plugin->env->session_end (session->plugin->env->cls, | 832 | session->plugin->env->session_end (session->plugin->env->cls, |
819 | &session->target, session); | 833 | &session->target, session); |
834 | |||
835 | if (session->nat_connection_timeout != GNUNET_SCHEDULER_NO_TASK) | ||
836 | { | ||
837 | GNUNET_SCHEDULER_cancel (session->nat_connection_timeout); | ||
838 | session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
839 | } | ||
840 | |||
820 | while (NULL != (pm = session->pending_messages_head)) | 841 | while (NULL != (pm = session->pending_messages_head)) |
821 | { | 842 | { |
822 | #if DEBUG_TCP | 843 | #if DEBUG_TCP |
@@ -840,7 +861,6 @@ disconnect_session (struct Session *session) | |||
840 | GNUNET_SYSERR); | 861 | GNUNET_SYSERR); |
841 | GNUNET_free (pm); | 862 | GNUNET_free (pm); |
842 | } | 863 | } |
843 | GNUNET_break (session->client != NULL); | ||
844 | if (session->receive_delay_task != GNUNET_SCHEDULER_NO_TASK) | 864 | if (session->receive_delay_task != GNUNET_SCHEDULER_NO_TASK) |
845 | { | 865 | { |
846 | GNUNET_SCHEDULER_cancel (session->receive_delay_task); | 866 | GNUNET_SCHEDULER_cancel (session->receive_delay_task); |
@@ -1008,6 +1028,22 @@ int session_lookup_it (void *cls, | |||
1008 | return GNUNET_NO; | 1028 | return GNUNET_NO; |
1009 | } | 1029 | } |
1010 | 1030 | ||
1031 | /** | ||
1032 | * Task cleaning up a NAT connection attempt after timeout | ||
1033 | */ | ||
1034 | |||
1035 | static void | ||
1036 | nat_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1037 | { | ||
1038 | struct Session *session = cls; | ||
1039 | |||
1040 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1041 | "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n", | ||
1042 | GNUNET_i2s (&session->target), tcp_address_to_string(NULL, session->addr, session->addrlen)); | ||
1043 | |||
1044 | disconnect_session (session); | ||
1045 | |||
1046 | } | ||
1011 | 1047 | ||
1012 | /** | 1048 | /** |
1013 | * Create a new session to transmit data to the target | 1049 | * Create a new session to transmit data to the target |
@@ -1148,6 +1184,9 @@ tcp_plugin_get_session (void *cls, | |||
1148 | session->addrlen = 0; | 1184 | session->addrlen = 0; |
1149 | session->addr = NULL; | 1185 | session->addr = NULL; |
1150 | session->ats_address_network_type = ats.value; | 1186 | session->ats_address_network_type = ats.value; |
1187 | session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed(NAT_TIMEOUT, | ||
1188 | &nat_connect_timeout, | ||
1189 | session); | ||
1151 | GNUNET_assert (session != NULL); | 1190 | GNUNET_assert (session != NULL); |
1152 | 1191 | ||
1153 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_put | 1192 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_put |
@@ -1166,33 +1205,7 @@ tcp_plugin_get_session (void *cls, | |||
1166 | "Running NAT client for `%4s' at `%s' failed\n", | 1205 | "Running NAT client for `%4s' at `%s' failed\n", |
1167 | GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs)); | 1206 | GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs)); |
1168 | 1207 | ||
1169 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove ( | 1208 | disconnect_session (session); |
1170 | plugin->nat_wait_conns, | ||
1171 | &address->peer.hashPubKey, | ||
1172 | session)); | ||
1173 | |||
1174 | /* cleaning up welcome msg and update statistics */ | ||
1175 | struct PendingMessage *pm; | ||
1176 | while (NULL != (pm = session->pending_messages_head)) | ||
1177 | { | ||
1178 | GNUNET_STATISTICS_update (session->plugin->env->stats, | ||
1179 | gettext_noop ("# bytes currently in TCP buffers"), | ||
1180 | -(int64_t) pm->message_size, GNUNET_NO); | ||
1181 | GNUNET_STATISTICS_update (session->plugin->env->stats, | ||
1182 | gettext_noop | ||
1183 | ("# bytes discarded by TCP (disconnect)"), | ||
1184 | pm->message_size, GNUNET_NO); | ||
1185 | GNUNET_CONTAINER_DLL_remove (session->pending_messages_head, | ||
1186 | session->pending_messages_tail, pm); | ||
1187 | GNUNET_free (pm); | ||
1188 | } | ||
1189 | |||
1190 | GNUNET_STATISTICS_update (session->plugin->env->stats, | ||
1191 | gettext_noop ("# TCP sessions active"), -1, | ||
1192 | GNUNET_NO); | ||
1193 | GNUNET_free_non_null (session->addr); | ||
1194 | GNUNET_free (session); | ||
1195 | session = NULL; | ||
1196 | return NULL; | 1209 | return NULL; |
1197 | } | 1210 | } |
1198 | } | 1211 | } |
@@ -1253,26 +1266,6 @@ int session_disconnect_it (void *cls, | |||
1253 | return GNUNET_YES; | 1266 | return GNUNET_YES; |
1254 | } | 1267 | } |
1255 | 1268 | ||
1256 | int session_nat_disconnect_it (void *cls, | ||
1257 | const GNUNET_HashCode * key, | ||
1258 | void *value) | ||
1259 | { | ||
1260 | struct Session *session = value; | ||
1261 | |||
1262 | if (session != NULL) | ||
1263 | { | ||
1264 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1265 | "Cleaning up pending NAT session for peer `%4s'\n", GNUNET_i2s (&session->target)); | ||
1266 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (session->plugin->nat_wait_conns, &session->target.hashPubKey, session)); | ||
1267 | GNUNET_SERVER_client_drop (session->client); | ||
1268 | GNUNET_SERVER_receive_done (session->client, GNUNET_SYSERR); | ||
1269 | GNUNET_free (session); | ||
1270 | } | ||
1271 | |||
1272 | return GNUNET_YES; | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | /** | 1269 | /** |
1277 | * Function that can be called to force a disconnect from the | 1270 | * Function that can be called to force a disconnect from the |
1278 | * specified neighbour. This should also cancel all previously | 1271 | * specified neighbour. This should also cancel all previously |
@@ -1305,10 +1298,7 @@ tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) | |||
1305 | { | 1298 | { |
1306 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1299 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1307 | "Cleaning up pending NAT session for peer `%4s'\n", GNUNET_i2s (target)); | 1300 | "Cleaning up pending NAT session for peer `%4s'\n", GNUNET_i2s (target)); |
1308 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->nat_wait_conns, &target->hashPubKey, nat_session)); | 1301 | disconnect_session (nat_session); |
1309 | GNUNET_SERVER_client_drop (nat_session->client); | ||
1310 | GNUNET_SERVER_receive_done (nat_session->client, GNUNET_SYSERR); | ||
1311 | GNUNET_free (nat_session); | ||
1312 | } | 1302 | } |
1313 | } | 1303 | } |
1314 | 1304 | ||
@@ -1565,6 +1555,12 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client, | |||
1565 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | 1555 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", |
1566 | "Found session for NAT probe!\n"); | 1556 | "Found session for NAT probe!\n"); |
1567 | 1557 | ||
1558 | if (session->nat_connection_timeout != GNUNET_SCHEDULER_NO_TASK) | ||
1559 | { | ||
1560 | GNUNET_SCHEDULER_cancel (session->nat_connection_timeout); | ||
1561 | session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
1562 | } | ||
1563 | |||
1568 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_remove | 1564 | GNUNET_assert (GNUNET_CONTAINER_multihashmap_remove |
1569 | (plugin->nat_wait_conns, | 1565 | (plugin->nat_wait_conns, |
1570 | &tcp_nat_probe->clientIdentity.hashPubKey, | 1566 | &tcp_nat_probe->clientIdentity.hashPubKey, |
@@ -2153,7 +2149,7 @@ libgnunet_plugin_transport_tcp_done (void *cls) | |||
2153 | /* Removing leftover sessions */ | 2149 | /* Removing leftover sessions */ |
2154 | GNUNET_CONTAINER_multihashmap_iterate(plugin->sessionmap, &session_disconnect_it, NULL); | 2150 | GNUNET_CONTAINER_multihashmap_iterate(plugin->sessionmap, &session_disconnect_it, NULL); |
2155 | /* Removing leftover NAT sessions */ | 2151 | /* Removing leftover NAT sessions */ |
2156 | GNUNET_CONTAINER_multihashmap_iterate(plugin->nat_wait_conns, &session_nat_disconnect_it, NULL); | 2152 | GNUNET_CONTAINER_multihashmap_iterate(plugin->nat_wait_conns, &session_disconnect_it, NULL); |
2157 | 2153 | ||
2158 | if (plugin->service != NULL) | 2154 | if (plugin->service != NULL) |
2159 | GNUNET_SERVICE_stop (plugin->service); | 2155 | GNUNET_SERVICE_stop (plugin->service); |