aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_tcp.c
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-06-10 14:09:14 +0000
committerNathan S. Evans <evans@in.tum.de>2010-06-10 14:09:14 +0000
commit61b479ac0ad609646ee3dd1fa3ba84205ee95f09 (patch)
tree154e4e250781ee22b4aa772bc22e06b8166d3a4d /src/transport/plugin_transport_tcp.c
parent81763b925d23a03e1899b945f83cf454fa7923a8 (diff)
downloadgnunet-61b479ac0ad609646ee3dd1fa3ba84205ee95f09.tar.gz
gnunet-61b479ac0ad609646ee3dd1fa3ba84205ee95f09.zip
working TCP PWNAT implementation (at least on my machine), also base testcase and reliability testcase
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r--src/transport/plugin_transport_tcp.c133
1 files changed, 82 insertions, 51 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 7fa586588..cdaef4b48 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -38,6 +38,7 @@
38#include "transport.h" 38#include "transport.h"
39 39
40#define DEBUG_TCP GNUNET_NO 40#define DEBUG_TCP GNUNET_NO
41#define DEBUG_TCP_NAT GNUNET_NO
41 42
42/** 43/**
43 * How long until we give up on transmitting the welcome message? 44 * How long until we give up on transmitting the welcome message?
@@ -838,9 +839,14 @@ run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
838 char *port_as_string; 839 char *port_as_string;
839 pid_t pid; 840 pid_t pid;
840 const struct sockaddr *sa = (const struct sockaddr *)addr; 841 const struct sockaddr *sa = (const struct sockaddr *)addr;
842#if DEBUG_TCP_NAT
843 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
844 _("called run_gnunet_nat_client addrlen %d others are %d and %d\n"), addrlen, sizeof (struct sockaddr), sizeof (struct sockaddr_in));
845#endif
841 846
842 if (addrlen < sizeof (struct sockaddr)) 847 if (addrlen < sizeof (struct sockaddr))
843 return; 848 return;
849
844 switch (sa->sa_family) 850 switch (sa->sa_family)
845 { 851 {
846 case AF_INET: 852 case AF_INET:
@@ -857,7 +863,7 @@ run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
857 } 863 }
858 864
859 GNUNET_asprintf(&port_as_string, "%d", plugin->adv_port); 865 GNUNET_asprintf(&port_as_string, "%d", plugin->adv_port);
860#if DEBUG_UDP_NAT 866#if DEBUG_TCP_NAT
861 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", 867 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
862 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->adv_port); 868 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->adv_port);
863#endif 869#endif
@@ -1046,9 +1052,15 @@ tcp_plugin_send (void *cls,
1046 if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) 1052 if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress)))
1047 return -1; /* NAT client only works with IPv4 addresses */ 1053 return -1; /* NAT client only works with IPv4 addresses */
1048 1054
1055
1049 if ( (plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && 1056 if ( (plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) &&
1050 (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) 1057 (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey)))
1051 { 1058 {
1059#if DEBUG_TCP_NAT
1060 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1061 "tcp",
1062 _("Found valid IPv4 NAT address!\n"));
1063#endif
1052 session = create_session (plugin, 1064 session = create_session (plugin,
1053 target, 1065 target,
1054 NULL, is_natd); 1066 NULL, is_natd);
@@ -1069,13 +1081,14 @@ tcp_plugin_send (void *cls,
1069 pm); 1081 pm);
1070 1082
1071 GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1083 GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1084#if DEBUG_TCP_NAT
1072 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1085 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1073 "tcp", 1086 "tcp",
1074 "Created NAT WAIT connection to `%4s' at `%s'\n", 1087 "Created NAT WAIT connection to `%4s' at `%s'\n",
1075 GNUNET_i2s (target), 1088 GNUNET_i2s (target),
1076 GNUNET_a2s (sb, sbs)); 1089 GNUNET_a2s (sb, sbs));
1077 1090#endif
1078 run_gnunet_nat_client(plugin, addr, addrlen); 1091 run_gnunet_nat_client(plugin, sb, sbs);
1079 return 0; 1092 return 0;
1080 } 1093 }
1081 else if ((plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) 1094 else if ((plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey)))
@@ -1412,6 +1425,9 @@ handle_tcp_nat_probe (void *cls,
1412 const struct sockaddr_in *s4; 1425 const struct sockaddr_in *s4;
1413 const struct sockaddr_in6 *s6; 1426 const struct sockaddr_in6 *s6;
1414 1427
1428#if DEBUG_TCP_NAT
1429 GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG, "tcp", "received tcp NAT probe\n");
1430#endif
1415 /* We have received a TCP NAT probe, meaning we (hopefully) initiated 1431 /* We have received a TCP NAT probe, meaning we (hopefully) initiated
1416 * a connection to this peer by running gnunet-nat-client. This peer 1432 * a connection to this peer by running gnunet-nat-client. This peer
1417 * received the punch message and now wants us to use the new connection 1433 * received the punch message and now wants us to use the new connection
@@ -1420,28 +1436,34 @@ handle_tcp_nat_probe (void *cls,
1420 */ 1436 */
1421 if (ntohs(message->size) != sizeof(struct TCP_NAT_ProbeMessage)) 1437 if (ntohs(message->size) != sizeof(struct TCP_NAT_ProbeMessage))
1422 { 1438 {
1439#if DEBUG_TCP_NAT
1440 GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG, "tcp", "Bad size fo tcp NAT probe, expected %d got %d.\n", sizeof(struct TCP_NAT_ProbeMessage), ntohs(message->size));
1441#endif
1423 GNUNET_break_op(0); 1442 GNUNET_break_op(0);
1424 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1425 return; 1443 return;
1426 } 1444 }
1427 tcp_nat_probe = (struct TCP_NAT_ProbeMessage *)message; 1445 tcp_nat_probe = (struct TCP_NAT_ProbeMessage *)message;
1428 1446
1429 if (GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey) == GNUNET_YES) 1447 if (GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey) == GNUNET_YES)
1430 { 1448 {
1449#if DEBUG_TCP_NAT
1450 GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG, "tcp", "Found session for NAT probe!\n");
1451#endif
1431 session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey); 1452 session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey);
1432 GNUNET_assert(session != NULL); 1453 GNUNET_assert(session != NULL);
1433 GNUNET_SERVER_client_keep (client); 1454 GNUNET_SERVER_client_keep (client);
1434 session->client = client; 1455 session->client = client;
1456 session->last_activity = GNUNET_TIME_absolute_get ();
1435 1457
1436 if (GNUNET_OK == 1458 if (GNUNET_OK ==
1437 GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) 1459 GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
1438 { 1460 {
1439#if DEBUG_TCP 1461#if DEBUG_TCP_NAT
1440 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1462 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1441 "tcp", 1463 "tcp",
1442 "Found address `%s' for incoming connection %p\n", 1464 "Found address `%s' for incoming connection %p\n",
1443 GNUNET_a2s (vaddr, alen), 1465 GNUNET_a2s (vaddr, alen),
1444 client); 1466 client);
1445#endif 1467#endif
1446 if (alen == sizeof (struct sockaddr_in)) 1468 if (alen == sizeof (struct sockaddr_in))
1447 { 1469 {
@@ -1476,7 +1498,6 @@ handle_tcp_nat_probe (void *cls,
1476 /* FIXME: free partial session? */ 1498 /* FIXME: free partial session? */
1477 } 1499 }
1478 1500
1479
1480 session->next = plugin->sessions; 1501 session->next = plugin->sessions;
1481 plugin->sessions = session; 1502 plugin->sessions = session;
1482 1503
@@ -1485,9 +1506,16 @@ handle_tcp_nat_probe (void *cls,
1485 1, 1506 1,
1486 GNUNET_NO); 1507 GNUNET_NO);
1487 /*GNUNET_SERVER_connect_socket (plugin->server, 1508 /*GNUNET_SERVER_connect_socket (plugin->server,
1488 client);*/ 1509 client->);*/
1510
1511 process_pending_messages (session);
1512 }
1513 else
1514 {
1515#if DEBUG_TCP_NAT
1516 GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG, "tcp", "Did NOT find session for NAT probe!\n");
1517#endif
1489 } 1518 }
1490 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1491} 1519}
1492 1520
1493/** 1521/**
@@ -1639,7 +1667,7 @@ handle_tcp_data (void *cls,
1639 1667
1640 if ((GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) || (ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE)) 1668 if ((GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) || (ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE))
1641 { 1669 {
1642 /* We don't want to propagate WELCOME messages up! */ 1670 /* We don't want to propagate WELCOME and NAT Probe messages up! */
1643 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1671 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1644 return; 1672 return;
1645 } 1673 }
@@ -1870,7 +1898,7 @@ tcp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
1870 1898
1871 if (bytes < 1) 1899 if (bytes < 1)
1872 { 1900 {
1873#if DEBUG_UDP_NAT 1901#if DEBUG_TCP_NAT
1874 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", 1902 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
1875 _("Finished reading from server stdout with code: %d\n"), bytes); 1903 _("Finished reading from server stdout with code: %d\n"), bytes);
1876#endif 1904#endif
@@ -1921,13 +1949,14 @@ tcp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
1921 return; 1949 return;
1922 } 1950 }
1923 1951
1952 in_addr.sin_family = AF_INET;
1953 in_addr.sin_port = htons(port);
1924 /** 1954 /**
1925 * We have received an ICMP response, ostensibly from a non-NAT'd peer 1955 * We have received an ICMP response, ostensibly from a non-NAT'd peer
1926 * that wants to connect to us! Send a message to establish a connection. 1956 * that wants to connect to us! Send a message to establish a connection.
1927 */ 1957 */
1928 sock = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, AF_INET, (struct sockaddr *)&in_addr, 1958 sock = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, AF_INET, (struct sockaddr *)&in_addr,
1929 sizeof(in_addr), GNUNET_SERVER_MAX_MESSAGE_SIZE); 1959 sizeof(in_addr), GNUNET_SERVER_MAX_MESSAGE_SIZE);
1930
1931 if (sock == NULL) 1960 if (sock == NULL)
1932 { 1961 {
1933 plugin->server_read_task = 1962 plugin->server_read_task =
@@ -1944,7 +1973,7 @@ tcp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
1944 tcp_probe_ctx->message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE); 1973 tcp_probe_ctx->message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
1945 memcpy(&tcp_probe_ctx->message.clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)); 1974 memcpy(&tcp_probe_ctx->message.clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity));
1946 tcp_probe_ctx->plugin = plugin; 1975 tcp_probe_ctx->plugin = plugin;
1947 1976 tcp_probe_ctx->sock = sock;
1948 tcp_probe_ctx->transmit_handle = GNUNET_CONNECTION_notify_transmit_ready (sock, 1977 tcp_probe_ctx->transmit_handle = GNUNET_CONNECTION_notify_transmit_ready (sock,
1949 ntohs(tcp_probe_ctx->message.header.size), 1978 ntohs(tcp_probe_ctx->message.header.size),
1950 GNUNET_TIME_UNIT_FOREVER_REL, 1979 GNUNET_TIME_UNIT_FOREVER_REL,
@@ -2107,18 +2136,20 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2107 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 2136 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2108 "transport-tcp", 2137 "transport-tcp",
2109 "BEHIND_NAT")) 2138 "BEHIND_NAT"))
2110 { 2139 {
2111 /* We are behind nat (according to the user) */ 2140 /* We are behind nat (according to the user) */
2112 if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES) 2141 if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES)
2142 {
2113 behind_nat = GNUNET_YES; 2143 behind_nat = GNUNET_YES;
2114 else 2144 }
2115 { 2145 else
2116 behind_nat = GNUNET_NO; 2146 {
2117 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n"); 2147 behind_nat = GNUNET_NO;
2118 } 2148 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n");
2119 } 2149 }
2120 else 2150 }
2121 behind_nat = GNUNET_NO; /* We are not behind nat! */ 2151 else
2152 behind_nat = GNUNET_NO; /* We are not behind nat! */
2122 2153
2123 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 2154 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2124 "transport-tcp", 2155 "transport-tcp",
@@ -2194,29 +2225,6 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2194 return NULL; 2225 return NULL;
2195 } 2226 }
2196 2227
2197 if (behind_nat)
2198 {
2199 if (GNUNET_YES != tcp_transport_start_nat_server(plugin))
2200 {
2201 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
2202 "tcp",
2203 _
2204 ("Failed to start %s required for NAT in %s!\n"),
2205 "gnunet-nat-server"
2206 "transport-tcp");
2207 GNUNET_free_non_null(external_address);
2208 GNUNET_free_non_null(internal_address);
2209 GNUNET_SERVICE_stop (service);
2210 return NULL;
2211 }
2212 }
2213
2214 if (allow_nat)
2215 {
2216 plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(100);
2217 GNUNET_assert(plugin->nat_wait_conns != NULL);
2218 }
2219
2220 if (aport == 0) 2228 if (aport == 0)
2221 aport = bport; 2229 aport = bport;
2222 plugin = GNUNET_malloc (sizeof (struct Plugin)); 2230 plugin = GNUNET_malloc (sizeof (struct Plugin));
@@ -2246,6 +2254,29 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2246 plugin->handlers[i].callback_cls = plugin; 2254 plugin->handlers[i].callback_cls = plugin;
2247 GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers); 2255 GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers);
2248 2256
2257 if (behind_nat == GNUNET_YES)
2258 {
2259 if (GNUNET_YES != tcp_transport_start_nat_server(plugin))
2260 {
2261 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
2262 "tcp",
2263 _
2264 ("Failed to start %s required for NAT in %s!\n"),
2265 "gnunet-nat-server"
2266 "transport-tcp");
2267 GNUNET_free_non_null(external_address);
2268 GNUNET_free_non_null(internal_address);
2269 GNUNET_SERVICE_stop (service);
2270 return NULL;
2271 }
2272 }
2273
2274 if (allow_nat == GNUNET_YES)
2275 {
2276 plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(100);
2277 GNUNET_assert(plugin->nat_wait_conns != NULL);
2278 }
2279
2249 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 2280 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
2250 "tcp", _("TCP transport listening on port %llu\n"), bport); 2281 "tcp", _("TCP transport listening on port %llu\n"), bport);
2251 if (aport != bport) 2282 if (aport != bport)