aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_tcp.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2012-03-02 15:39:47 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2012-03-02 15:39:47 +0000
commitd81a110b209d98e5db18fbd5d9516bec37138d4f (patch)
tree71c39e770cd1f15738c1d859b98bf5781f899cf6 /src/transport/plugin_transport_tcp.c
parenta4d2d006ed644cd965d7d80f8e4c4ad4988fc972 (diff)
downloadgnunet-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.c104
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
46GNUNET_NETWORK_STRUCT_BEGIN 54GNUNET_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
1035static void
1036nat_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
1256int 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);