aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-06-26 22:26:57 +0000
committerChristian Grothoff <christian@grothoff.org>2011-06-26 22:26:57 +0000
commit1791f39fa6dc0bc37d14af98a0684fe1a23fc697 (patch)
tree66b33b772226f77289f669e6d9e4afa03b42a22b
parent8a3016481ba6aeb36de3950a56e641dda53ca544 (diff)
downloadgnunet-1791f39fa6dc0bc37d14af98a0684fe1a23fc697.tar.gz
gnunet-1791f39fa6dc0bc37d14af98a0684fe1a23fc697.zip
partial fix of the NAT troubles
-rw-r--r--src/nat/nat.c43
-rw-r--r--src/transport/gnunet-service-transport.c653
-rw-r--r--src/transport/plugin_transport_tcp.c5
-rw-r--r--src/transport/test_transport_api.c102
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf2
-rw-r--r--src/transport/transport.h2
-rw-r--r--src/util/connection.c3
7 files changed, 504 insertions, 306 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c
index e92f57259..99d2bbc7c 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -178,6 +178,11 @@ struct GNUNET_NAT_Handle
178 GNUNET_SCHEDULER_TaskIdentifier server_read_task; 178 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
179 179
180 /** 180 /**
181 * ID of interface IP-scan task
182 */
183 GNUNET_SCHEDULER_TaskIdentifier ifc_task;
184
185 /**
181 * The process id of the server process (if behind NAT) 186 * The process id of the server process (if behind NAT)
182 */ 187 */
183 struct GNUNET_OS_Process *server_proc; 188 struct GNUNET_OS_Process *server_proc;
@@ -857,6 +862,27 @@ start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
857 862
858 863
859/** 864/**
865 * Task to scan the local network interfaces for IP addresses.
866 *
867 * @param cls the NAT handle
868 * @param tc scheduler context
869 */
870static void
871list_interfaces (void *cls,
872 const struct GNUNET_SCHEDULER_TaskContext *tc)
873{
874 struct GNUNET_NAT_Handle *h = cls;
875
876 h->ifc_task = GNUNET_SCHEDULER_NO_TASK;
877 GNUNET_OS_network_interfaces_list (&process_interfaces, h);
878#if 0
879 h->ifc_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FIXME,
880 &list_interfaces, h);
881#endif
882}
883
884
885/**
860 * Attempt to enable port redirection and detect public IP address contacting 886 * Attempt to enable port redirection and detect public IP address contacting
861 * UPnP or NAT-PMP routers on the local network. Use addr to specify to which 887 * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
862 * of the local host's addresses should the external port be mapped. The port 888 * of the local host's addresses should the external port be mapped. The port
@@ -889,6 +915,10 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
889 struct in_addr in_addr; 915 struct in_addr in_addr;
890 unsigned int i; 916 unsigned int i;
891 917
918 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
919 "Registered with NAT service at port %u with %u IP bound local addresses\n",
920 (unsigned int) adv_port,
921 num_addrs);
892 h = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle)); 922 h = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle));
893 h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS; 923 h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS;
894 h->cfg = cfg; 924 h->cfg = cfg;
@@ -1016,7 +1046,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1016 1046
1017 if (NULL != h->address_callback) 1047 if (NULL != h->address_callback)
1018 { 1048 {
1019 GNUNET_OS_network_interfaces_list (&process_interfaces, h); 1049 h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces, h);
1020 h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, 1050 h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
1021 HOSTNAME_RESOLVE_TIMEOUT, 1051 HOSTNAME_RESOLVE_TIMEOUT,
1022 &process_hostname_ip, 1052 &process_hostname_ip,
@@ -1053,6 +1083,11 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
1053 GNUNET_SCHEDULER_cancel (h->server_read_task); 1083 GNUNET_SCHEDULER_cancel (h->server_read_task);
1054 h->server_read_task = GNUNET_SCHEDULER_NO_TASK; 1084 h->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1055 } 1085 }
1086 if (GNUNET_SCHEDULER_NO_TASK != h->ifc_task)
1087 {
1088 GNUNET_SCHEDULER_cancel (h->ifc_task);
1089 h->ifc_task = GNUNET_SCHEDULER_NO_TASK;
1090 }
1056 if (NULL != h->server_proc) 1091 if (NULL != h->server_proc)
1057 { 1092 {
1058 if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM)) 1093 if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM))
@@ -1172,7 +1207,7 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
1172 struct LocalAddressList *pos; 1207 struct LocalAddressList *pos;
1173 const struct sockaddr_in *in4; 1208 const struct sockaddr_in *in4;
1174 const struct sockaddr_in6 *in6; 1209 const struct sockaddr_in6 *in6;
1175 1210
1176 if ( (addrlen != sizeof (struct in_addr)) && 1211 if ( (addrlen != sizeof (struct in_addr)) &&
1177 (addrlen != sizeof (struct in6_addr)) ) 1212 (addrlen != sizeof (struct in6_addr)) )
1178 { 1213 {
@@ -1202,7 +1237,9 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
1202 } 1237 }
1203 pos = pos->next; 1238 pos = pos->next;
1204 } 1239 }
1205 return GNUNET_YES; 1240 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1241 "Asked to validate one of my addresses and validation failed!\n");
1242 return GNUNET_NO;
1206} 1243}
1207 1244
1208 1245
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 2010c8d51..51e84e1dd 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -44,9 +44,9 @@
44 44
45#define DEBUG_BLACKLIST GNUNET_NO 45#define DEBUG_BLACKLIST GNUNET_NO
46 46
47#define DEBUG_PING_PONG GNUNET_YES 47#define DEBUG_PING_PONG GNUNET_NO
48 48
49#define DEBUG_TRANSPORT_HELLO GNUNET_YES 49#define DEBUG_TRANSPORT_HELLO GNUNET_NO
50 50
51#define DEBUG_ATS GNUNET_NO 51#define DEBUG_ATS GNUNET_NO
52 52
@@ -750,7 +750,7 @@ struct CheckHelloValidatedContext;
750/** 750/**
751 * Entry in map of all HELLOs awaiting validation. 751 * Entry in map of all HELLOs awaiting validation.
752 */ 752 */
753struct ValidationEntry 753struct ValidationEntry
754{ 754{
755 755
756 /** 756 /**
@@ -1675,56 +1675,73 @@ a2s (const char *plugin,
1675} 1675}
1676 1676
1677 1677
1678
1679
1678/** 1680/**
1679 * Mark the given FAL entry as 'connected' (and hence preferred for 1681 * Iterator to free entries in the validation_map.
1680 * sending); also mark all others for the same peer as 'not connected'
1681 * (since only one can be preferred).
1682 * 1682 *
1683 * @param fal address to set to 'connected' 1683 * @param cls closure (unused)
1684 * @param key current key code
1685 * @param value value in the hash map (validation to abort)
1686 * @return GNUNET_YES (always)
1684 */ 1687 */
1685static void 1688static int
1686mark_address_connected (struct ForeignAddressList *fal) 1689abort_validation (void *cls,
1690 const GNUNET_HashCode * key,
1691 void *value)
1687{ 1692{
1688 struct ForeignAddressList *pos; 1693 struct ValidationEntry *va = value;
1689 int cnt;
1690 1694
1691 GNUNET_assert (GNUNET_YES == fal->validated); 1695 if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
1692 if (fal->connected == GNUNET_YES) 1696 GNUNET_SCHEDULER_cancel (va->timeout_task);
1693 return; /* nothing to do */ 1697 GNUNET_free (va->transport_name);
1694 cnt = GNUNET_YES; 1698 if (va->chvc != NULL)
1695 pos = fal->ready_list->addresses;
1696 while (pos != NULL)
1697 { 1699 {
1698 if (GNUNET_YES == pos->connected) 1700 va->chvc->ve_count--;
1701 if (va->chvc->ve_count == 0)
1699 { 1702 {
1700#if DEBUG_TRANSPORT 1703 GNUNET_CONTAINER_DLL_remove (chvc_head,
1701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1704 chvc_tail,
1702 "Marking address `%s' as no longer connected (due to connect on other address)\n", 1705 va->chvc);
1703 a2s (pos->ready_list->plugin->short_name, 1706 GNUNET_free (va->chvc);
1704 pos->addr,
1705 pos->addrlen));
1706#endif
1707 GNUNET_break (cnt == GNUNET_YES);
1708 cnt = GNUNET_NO;
1709 pos->connected = GNUNET_NO;
1710 GNUNET_STATISTICS_update (stats,
1711 gettext_noop ("# connected addresses"),
1712 -1,
1713 GNUNET_NO);
1714 } 1707 }
1715 pos = pos->next; 1708 va->chvc = NULL;
1716 }
1717 fal->connected = GNUNET_YES;
1718 if (GNUNET_YES == cnt)
1719 {
1720 GNUNET_STATISTICS_update (stats,
1721 gettext_noop ("# connected addresses"),
1722 1,
1723 GNUNET_NO);
1724 } 1709 }
1710 GNUNET_free (va);
1711 return GNUNET_YES;
1712}
1713
1714
1715/**
1716 * HELLO validation cleanup task (validation failed).
1717 *
1718 * @param cls the 'struct ValidationEntry' that failed
1719 * @param tc scheduler context (unused)
1720 */
1721static void
1722timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1723{
1724 struct ValidationEntry *va = cls;
1725 struct GNUNET_PeerIdentity pid;
1726
1727 va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1728 GNUNET_STATISTICS_update (stats,
1729 gettext_noop ("# address validation timeouts"),
1730 1,
1731 GNUNET_NO);
1732 GNUNET_CRYPTO_hash (&va->publicKey,
1733 sizeof (struct
1734 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1735 &pid.hashPubKey);
1736 GNUNET_break (GNUNET_OK ==
1737 GNUNET_CONTAINER_multihashmap_remove (validation_map,
1738 &pid.hashPubKey,
1739 va));
1740 abort_validation (NULL, NULL, va);
1725} 1741}
1726 1742
1727 1743
1744
1728/** 1745/**
1729 * Send the specified message to the specified client. Since multiple 1746 * Send the specified message to the specified client. Since multiple
1730 * messages may be pending for the same client at a time, this code 1747 * messages may be pending for the same client at a time, this code
@@ -1808,6 +1825,17 @@ transmit_send_ok (struct TransportClient *client,
1808 1825
1809 1826
1810/** 1827/**
1828 * Mark the given FAL entry as 'connected' (and hence preferred for
1829 * sending); also mark all others for the same peer as 'not connected'
1830 * (since only one can be preferred).
1831 *
1832 * @param fal address to set to 'connected'
1833 */
1834static void
1835mark_address_connected (struct ForeignAddressList *fal);
1836
1837
1838/**
1811 * Function called by the GNUNET_TRANSPORT_TransmitFunction 1839 * Function called by the GNUNET_TRANSPORT_TransmitFunction
1812 * upon "completion" of a send request. This tells the API 1840 * upon "completion" of a send request. This tells the API
1813 * that it is now legal to send another message to the given 1841 * that it is now legal to send another message to the given
@@ -1888,122 +1916,6 @@ transmit_send_continuation (void *cls,
1888 1916
1889 1917
1890/** 1918/**
1891 * Find an address in any of the available transports for
1892 * the given neighbour that would be good for message
1893 * transmission. This is essentially the transport selection
1894 * routine.
1895 *
1896 * @param neighbour for whom to select an address
1897 * @return selected address, NULL if we have none
1898 */
1899struct ForeignAddressList *
1900find_ready_address(struct NeighbourList *neighbour)
1901{
1902 struct ReadyList *head = neighbour->plugins;
1903 struct ForeignAddressList *addresses;
1904 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1905 struct ForeignAddressList *best_address;
1906
1907 /* Hack to prefer unix domain sockets */
1908 struct ForeignAddressList *unix_address = NULL;
1909
1910 best_address = NULL;
1911 while (head != NULL)
1912 {
1913 addresses = head->addresses;
1914 while (addresses != NULL)
1915 {
1916 if ( (addresses->timeout.abs_value < now.abs_value) &&
1917 (addresses->connected == GNUNET_YES) )
1918 {
1919#if DEBUG_TRANSPORT
1920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1921 "Marking long-time inactive connection to `%4s' as down.\n",
1922 GNUNET_i2s (&neighbour->id));
1923#endif
1924 GNUNET_STATISTICS_update (stats,
1925 gettext_noop ("# connected addresses"),
1926 -1,
1927 GNUNET_NO);
1928 addresses->connected = GNUNET_NO;
1929 }
1930 addresses = addresses->next;
1931 }
1932
1933 addresses = head->addresses;
1934 while (addresses != NULL)
1935 {
1936#if DEBUG_TRANSPORT > 1
1937 if (addresses->addr != NULL)
1938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1939 "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
1940 a2s (head->plugin->short_name,
1941 addresses->addr,
1942 addresses->addrlen),
1943 GNUNET_i2s (&neighbour->id),
1944 addresses->connected,
1945 addresses->in_transmit,
1946 addresses->validated,
1947 addresses->connect_attempts,
1948 (unsigned long long) addresses->timeout.abs_value,
1949 (unsigned int) addresses->distance);
1950#endif
1951 if (0==strcmp(head->plugin->short_name,"unix"))
1952 {
1953 if ((unix_address == NULL) || ((unix_address != NULL) &&
1954 (addresses->latency.rel_value < unix_address->latency.rel_value)))
1955 unix_address = addresses;
1956 }
1957 if ( ( (best_address == NULL) ||
1958 (addresses->connected == GNUNET_YES) ||
1959 (best_address->connected == GNUNET_NO) ) &&
1960 (addresses->in_transmit == GNUNET_NO) &&
1961 ( (best_address == NULL) ||
1962 (addresses->latency.rel_value < best_address->latency.rel_value)) )
1963 best_address = addresses;
1964 /* FIXME: also give lower-latency addresses that are not
1965 connected a chance some times... */
1966 addresses = addresses->next;
1967 }
1968 if (unix_address != NULL)
1969 break;
1970 head = head->next;
1971 }
1972 if (unix_address != NULL)
1973 {
1974 best_address = unix_address;
1975#if DEBUG_TRANSPORT
1976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1977 "Found UNIX address, forced this address\n");
1978#endif
1979 }
1980 if (best_address != NULL)
1981 {
1982#if DEBUG_TRANSPORT
1983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1984 "Best address found (`%s') has latency of %llu ms.\n",
1985 (best_address->addrlen > 0)
1986 ? a2s (best_address->ready_list->plugin->short_name,
1987 best_address->addr,
1988 best_address->addrlen)
1989 : "<inbound>",
1990 best_address->latency.rel_value);
1991#endif
1992 }
1993 else
1994 {
1995 GNUNET_STATISTICS_update (stats,
1996 gettext_noop ("# transmission attempts failed (no address)"),
1997 1,
1998 GNUNET_NO);
1999 }
2000
2001 return best_address;
2002
2003}
2004
2005
2006/**
2007 * We should re-try transmitting to the given peer, 1919 * We should re-try transmitting to the given peer,
2008 * hopefully we've learned something in the meantime. 1920 * hopefully we've learned something in the meantime.
2009 */ 1921 */
@@ -2228,6 +2140,248 @@ transmit_to_peer (struct TransportClient *client,
2228 2140
2229 2141
2230/** 2142/**
2143 * Send a plain PING (without address or our HELLO) to the given
2144 * foreign address to try to establish a connection (and validate
2145 * that the other peer is really who he claimed he is).
2146 *
2147 * @param n neighbour to PING
2148 */
2149static void
2150transmit_plain_ping (struct NeighbourList *n)
2151{
2152 struct ValidationEntry *ve;
2153 struct TransportPingMessage ping;
2154 struct ReadyList *rl;
2155 struct TransportPlugin *plugin;
2156 struct ForeignAddressList *fal;
2157
2158 if (! n->public_key_valid)
2159 {
2160 /* This should not happen since the other peer
2161 should send us a HELLO prior to sending his
2162 PING */
2163 GNUNET_break_op (0);
2164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2165 "Could not transmit plain PING to `%s': public key not known\n",
2166 GNUNET_i2s (&n->id));
2167 return;
2168 }
2169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2170 "Looking for addresses to transmit plain PING to `%s'\n",
2171 GNUNET_i2s (&n->id));
2172 for (rl = n->plugins; rl != NULL; rl = rl->next)
2173 {
2174 plugin = rl->plugin;
2175 for (fal = rl->addresses; fal != NULL; fal = fal->next)
2176 {
2177 if (! fal->connected)
2178 continue;
2179 ve = GNUNET_malloc (sizeof (struct ValidationEntry));
2180 ve->transport_name = GNUNET_strdup (plugin->short_name);
2181 ve->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2182 UINT_MAX);
2183 ve->send_time = GNUNET_TIME_absolute_get();
2184 ve->session = fal->session;
2185 memcpy(&ve->publicKey,
2186 &n->publicKey,
2187 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2188 ve->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
2189 &timeout_hello_validation,
2190 ve);
2191 GNUNET_CONTAINER_multihashmap_put (validation_map,
2192 &n->id.hashPubKey,
2193 ve,
2194 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2195 ping.header.size = htons(sizeof(struct TransportPingMessage));
2196 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2197 ping.challenge = htonl(ve->challenge);
2198 memcpy(&ping.target, &n->id, sizeof(struct GNUNET_PeerIdentity));
2199 GNUNET_STATISTICS_update (stats,
2200 gettext_noop ("# PING without HELLO messages sent"),
2201 1,
2202 GNUNET_NO);
2203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2204 "Transmitting plain PING to `%s'\n",
2205 GNUNET_i2s (&n->id));
2206 transmit_to_peer (NULL,
2207 fal,
2208 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2209 HELLO_VERIFICATION_TIMEOUT,
2210 (const char*) &ping, sizeof (ping),
2211 GNUNET_YES, n);
2212 }
2213 }
2214}
2215
2216
2217/**
2218 * Mark the given FAL entry as 'connected' (and hence preferred for
2219 * sending); also mark all others for the same peer as 'not connected'
2220 * (since only one can be preferred).
2221 *
2222 * @param fal address to set to 'connected'
2223 */
2224static void
2225mark_address_connected (struct ForeignAddressList *fal)
2226{
2227 struct ForeignAddressList *pos;
2228 int cnt;
2229
2230 GNUNET_assert (GNUNET_YES == fal->validated);
2231 if (fal->connected == GNUNET_YES)
2232 return; /* nothing to do */
2233 cnt = GNUNET_YES;
2234 pos = fal->ready_list->addresses;
2235 while (pos != NULL)
2236 {
2237 if (GNUNET_YES == pos->connected)
2238 {
2239#if DEBUG_TRANSPORT
2240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2241 "Marking address `%s' as no longer connected (due to connect on other address)\n",
2242 a2s (pos->ready_list->plugin->short_name,
2243 pos->addr,
2244 pos->addrlen));
2245#endif
2246 GNUNET_break (cnt == GNUNET_YES);
2247 cnt = GNUNET_NO;
2248 pos->connected = GNUNET_NO;
2249 GNUNET_STATISTICS_update (stats,
2250 gettext_noop ("# connected addresses"),
2251 -1,
2252 GNUNET_NO);
2253 }
2254 pos = pos->next;
2255 }
2256 fal->connected = GNUNET_YES;
2257 if (GNUNET_YES == cnt)
2258 {
2259 GNUNET_STATISTICS_update (stats,
2260 gettext_noop ("# connected addresses"),
2261 1,
2262 GNUNET_NO);
2263 }
2264}
2265
2266
2267/**
2268 * Find an address in any of the available transports for
2269 * the given neighbour that would be good for message
2270 * transmission. This is essentially the transport selection
2271 * routine.
2272 *
2273 * @param neighbour for whom to select an address
2274 * @return selected address, NULL if we have none
2275 */
2276struct ForeignAddressList *
2277find_ready_address(struct NeighbourList *neighbour)
2278{
2279 struct ReadyList *head = neighbour->plugins;
2280 struct ForeignAddressList *addresses;
2281 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
2282 struct ForeignAddressList *best_address;
2283
2284 /* Hack to prefer unix domain sockets */
2285 struct ForeignAddressList *unix_address = NULL;
2286
2287 best_address = NULL;
2288 while (head != NULL)
2289 {
2290 addresses = head->addresses;
2291 while (addresses != NULL)
2292 {
2293 if ( (addresses->timeout.abs_value < now.abs_value) &&
2294 (addresses->connected == GNUNET_YES) )
2295 {
2296#if DEBUG_TRANSPORT
2297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2298 "Marking long-time inactive connection to `%4s' as down.\n",
2299 GNUNET_i2s (&neighbour->id));
2300#endif
2301 GNUNET_STATISTICS_update (stats,
2302 gettext_noop ("# connected addresses"),
2303 -1,
2304 GNUNET_NO);
2305 addresses->connected = GNUNET_NO;
2306 }
2307 addresses = addresses->next;
2308 }
2309
2310 addresses = head->addresses;
2311 while (addresses != NULL)
2312 {
2313#if DEBUG_TRANSPORT
2314 if (addresses->addr != NULL)
2315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2316 "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
2317 a2s (head->plugin->short_name,
2318 addresses->addr,
2319 addresses->addrlen),
2320 GNUNET_i2s (&neighbour->id),
2321 addresses->connected,
2322 addresses->in_transmit,
2323 addresses->validated,
2324 addresses->connect_attempts,
2325 (unsigned long long) addresses->timeout.abs_value,
2326 (unsigned int) addresses->distance);
2327#endif
2328 if (0==strcmp(head->plugin->short_name,"unix"))
2329 {
2330 if ( (unix_address == NULL) ||
2331 ( (unix_address != NULL) &&
2332 (addresses->latency.rel_value < unix_address->latency.rel_value) ) )
2333 unix_address = addresses;
2334 }
2335 if ( ( (best_address == NULL) ||
2336 (addresses->connected == GNUNET_YES) ||
2337 (best_address->connected == GNUNET_NO) ) &&
2338 (addresses->in_transmit == GNUNET_NO) &&
2339 ( (best_address == NULL) ||
2340 (addresses->latency.rel_value < best_address->latency.rel_value)) )
2341 best_address = addresses;
2342 /* FIXME: also give lower-latency addresses that are not
2343 connected a chance some times... */
2344 addresses = addresses->next;
2345 }
2346 if (unix_address != NULL)
2347 break;
2348 head = head->next;
2349 }
2350 if (unix_address != NULL)
2351 {
2352 best_address = unix_address;
2353#if DEBUG_TRANSPORT
2354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2355 "Found UNIX address, forced this address\n");
2356#endif
2357 }
2358 if (best_address != NULL)
2359 {
2360#if DEBUG_TRANSPORT
2361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2362 "Best address found (`%s') has latency of %llu ms.\n",
2363 (best_address->addrlen > 0)
2364 ? a2s (best_address->ready_list->plugin->short_name,
2365 best_address->addr,
2366 best_address->addrlen)
2367 : "<inbound>",
2368 best_address->latency.rel_value);
2369#endif
2370 }
2371 else
2372 {
2373 GNUNET_STATISTICS_update (stats,
2374 gettext_noop ("# transmission attempts failed (no address)"),
2375 1,
2376 GNUNET_NO);
2377 }
2378
2379 return best_address;
2380
2381}
2382
2383
2384/**
2231 * FIXME: document. 2385 * FIXME: document.
2232 */ 2386 */
2233struct GeneratorContext 2387struct GeneratorContext
@@ -2302,9 +2456,10 @@ refresh_hello ()
2302 GNUNET_free_non_null (our_hello); 2456 GNUNET_free_non_null (our_hello);
2303 our_hello = hello; 2457 our_hello = hello;
2304 GNUNET_PEERINFO_add_peer (peerinfo, our_hello); 2458 GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
2305 npos = neighbours; 2459 for (npos = neighbours; npos != NULL; npos = npos->next)
2306 while (npos != NULL)
2307 { 2460 {
2461 if (! npos->received_pong)
2462 continue;
2308#if DEBUG_TRANSPORT 2463#if DEBUG_TRANSPORT
2309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 2464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2310 "Transmitting updated `%s' to neighbour `%4s'\n", 2465 "Transmitting updated `%s' to neighbour `%4s'\n",
@@ -2319,7 +2474,6 @@ refresh_hello ()
2319 (const char *) our_hello, 2474 (const char *) our_hello,
2320 GNUNET_HELLO_size(our_hello), 2475 GNUNET_HELLO_size(our_hello),
2321 GNUNET_NO, npos); 2476 GNUNET_NO, npos);
2322 npos = npos->next;
2323 } 2477 }
2324} 2478}
2325 2479
@@ -2611,6 +2765,14 @@ plugin_env_notify_address (void *cls,
2611 struct OwnAddressList *al; 2765 struct OwnAddressList *al;
2612 struct OwnAddressList *prev; 2766 struct OwnAddressList *prev;
2613 2767
2768 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2769 (add_remove == GNUNET_YES)
2770 ? "Adding `%s':%s to the set of our addresses\n"
2771 : "Removing `%s':%s from the set of our addresses\n",
2772 a2s (p->short_name,
2773 addr, addrlen),
2774 p->short_name);
2775
2614 GNUNET_assert (addr != NULL); 2776 GNUNET_assert (addr != NULL);
2615 if (GNUNET_NO == add_remove) 2777 if (GNUNET_NO == add_remove)
2616 { 2778 {
@@ -2666,7 +2828,7 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
2666 } 2828 }
2667#if DEBUG_TRANSPORT 2829#if DEBUG_TRANSPORT
2668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2669 "Notifying clients about connection from `%s'\n", 2831 "Notifying clients about connection with `%s'\n",
2670 GNUNET_i2s (peer)); 2832 GNUNET_i2s (peer));
2671#endif 2833#endif
2672 GNUNET_STATISTICS_update (stats, 2834 GNUNET_STATISTICS_update (stats,
@@ -3021,71 +3183,6 @@ check_address_exists (void *cls,
3021} 3183}
3022 3184
3023 3185
3024
3025/**
3026 * Iterator to free entries in the validation_map.
3027 *
3028 * @param cls closure (unused)
3029 * @param key current key code
3030 * @param value value in the hash map (validation to abort)
3031 * @return GNUNET_YES (always)
3032 */
3033static int
3034abort_validation (void *cls,
3035 const GNUNET_HashCode * key,
3036 void *value)
3037{
3038 struct ValidationEntry *va = value;
3039
3040 if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
3041 GNUNET_SCHEDULER_cancel (va->timeout_task);
3042 GNUNET_free (va->transport_name);
3043 if (va->chvc != NULL)
3044 {
3045 va->chvc->ve_count--;
3046 if (va->chvc->ve_count == 0)
3047 {
3048 GNUNET_CONTAINER_DLL_remove (chvc_head,
3049 chvc_tail,
3050 va->chvc);
3051 GNUNET_free (va->chvc);
3052 }
3053 va->chvc = NULL;
3054 }
3055 GNUNET_free (va);
3056 return GNUNET_YES;
3057}
3058
3059
3060/**
3061 * HELLO validation cleanup task (validation failed).
3062 *
3063 * @param cls the 'struct ValidationEntry' that failed
3064 * @param tc scheduler context (unused)
3065 */
3066static void
3067timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3068{
3069 struct ValidationEntry *va = cls;
3070 struct GNUNET_PeerIdentity pid;
3071
3072 va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
3073 GNUNET_STATISTICS_update (stats,
3074 gettext_noop ("# address validation timeouts"),
3075 1,
3076 GNUNET_NO);
3077 GNUNET_CRYPTO_hash (&va->publicKey,
3078 sizeof (struct
3079 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3080 &pid.hashPubKey);
3081 GNUNET_break (GNUNET_OK ==
3082 GNUNET_CONTAINER_multihashmap_remove (validation_map,
3083 &pid.hashPubKey,
3084 va));
3085 abort_validation (NULL, NULL, va);
3086}
3087
3088
3089static void 3186static void
3090neighbour_timeout_task (void *cls, 3187neighbour_timeout_task (void *cls,
3091 const struct GNUNET_SCHEDULER_TaskContext *tc) 3188 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -4150,7 +4247,8 @@ check_pending_validation (void *cls,
4150 &my_identity, 4247 &my_identity,
4151 sizeof (struct GNUNET_PeerIdentity))) 4248 sizeof (struct GNUNET_PeerIdentity)))
4152 { 4249 {
4153 char * peer; 4250 char * peer;
4251
4154 GNUNET_asprintf(&peer, "%s",GNUNET_i2s (&pong->pid)); 4252 GNUNET_asprintf(&peer, "%s",GNUNET_i2s (&pong->pid));
4155#if DEBUG_TRANSPORT 4253#if DEBUG_TRANSPORT
4156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 4254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -4185,11 +4283,17 @@ check_pending_validation (void *cls,
4185 if (oal == NULL) 4283 if (oal == NULL)
4186 { 4284 {
4187 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 4285 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4188 _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"), 4286 _("Not accepting PONG from `%s' with address `%s' since I cannot confirm using this address.\n"),
4287 GNUNET_i2s (&pong->pid),
4189 a2s (ve->transport_name, 4288 a2s (ve->transport_name,
4190 &addr[slen], 4289 &addr[slen],
4191 alen)); 4290 alen));
4291 /* FIXME: since the sender of the PONG currently uses the
4292 wrong address (see FIMXE there!), we cannot run a
4293 proper check here... */
4294#if FIXME_URGENT
4192 return GNUNET_NO; 4295 return GNUNET_NO;
4296#endif
4193 } 4297 }
4194 if (GNUNET_OK != 4298 if (GNUNET_OK !=
4195 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING, 4299 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
@@ -4323,9 +4427,11 @@ handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
4323 sizeof (struct GNUNET_PeerIdentity))) 4427 sizeof (struct GNUNET_PeerIdentity)))
4324 { 4428 {
4325 /* PONG send to self, ignore */ 4429 /* PONG send to self, ignore */
4430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4431 "Receiving `%s' message from myself\n",
4432 "PONG");
4326 return; 4433 return;
4327 } 4434 }
4328
4329#if DEBUG_TRANSPORT > 1 4435#if DEBUG_TRANSPORT > 1
4330 /* we get tons of these that just get discarded, only log 4436 /* we get tons of these that just get discarded, only log
4331 if we are quite verbose */ 4437 if we are quite verbose */
@@ -4740,9 +4846,11 @@ process_hello (struct TransportPlugin *plugin,
4740 const struct GNUNET_HELLO_Message *hello; 4846 const struct GNUNET_HELLO_Message *hello;
4741 struct CheckHelloValidatedContext *chvc; 4847 struct CheckHelloValidatedContext *chvc;
4742 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey; 4848 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
4849 struct NeighbourList *n;
4743#if DEBUG_TRANSPORT_HELLO > 2 4850#if DEBUG_TRANSPORT_HELLO > 2
4744 char *my_id; 4851 char *my_id;
4745#endif 4852#endif
4853
4746 hsize = ntohs (message->size); 4854 hsize = ntohs (message->size);
4747 if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) || 4855 if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
4748 (hsize < sizeof (struct GNUNET_MessageHeader))) 4856 (hsize < sizeof (struct GNUNET_MessageHeader)))
@@ -4755,21 +4863,6 @@ process_hello (struct TransportPlugin *plugin,
4755 1, 4863 1,
4756 GNUNET_NO); 4864 GNUNET_NO);
4757 4865
4758 /* first, check if load is too high */
4759 if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
4760 {
4761 GNUNET_STATISTICS_update (stats,
4762 gettext_noop ("# HELLOs ignored due to high load"),
4763 1,
4764 GNUNET_NO);
4765#if DEBUG_TRANSPORT_HELLO
4766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4767 "Ignoring `%s' for `%4s', load too high.\n",
4768 "HELLO",
4769 GNUNET_i2s (&target));
4770#endif
4771 return GNUNET_OK;
4772 }
4773 hello = (const struct GNUNET_HELLO_Message *) message; 4866 hello = (const struct GNUNET_HELLO_Message *) message;
4774 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey)) 4867 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
4775 { 4868 {
@@ -4782,7 +4875,6 @@ process_hello (struct TransportPlugin *plugin,
4782 GNUNET_break_op (0); 4875 GNUNET_break_op (0);
4783 return GNUNET_SYSERR; 4876 return GNUNET_SYSERR;
4784 } 4877 }
4785
4786 GNUNET_CRYPTO_hash (&publicKey, 4878 GNUNET_CRYPTO_hash (&publicKey,
4787 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 4879 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
4788 &target.hashPubKey); 4880 &target.hashPubKey);
@@ -4793,7 +4885,6 @@ process_hello (struct TransportPlugin *plugin,
4793 "HELLO", 4885 "HELLO",
4794 GNUNET_i2s (&target)); 4886 GNUNET_i2s (&target));
4795#endif 4887#endif
4796
4797 if (0 == memcmp (&my_identity, 4888 if (0 == memcmp (&my_identity,
4798 &target, 4889 &target,
4799 sizeof (struct GNUNET_PeerIdentity))) 4890 sizeof (struct GNUNET_PeerIdentity)))
@@ -4804,6 +4895,31 @@ process_hello (struct TransportPlugin *plugin,
4804 GNUNET_NO); 4895 GNUNET_NO);
4805 return GNUNET_OK; 4896 return GNUNET_OK;
4806 } 4897 }
4898 n = find_neighbour (&target);
4899 if ( (NULL != n) &&
4900 (! n->public_key_valid) )
4901 {
4902 GNUNET_HELLO_get_key (hello, &n->publicKey);
4903 n->public_key_valid = GNUNET_YES;
4904 }
4905
4906 /* check if load is too high before doing expensive stuff */
4907 if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
4908 {
4909 GNUNET_STATISTICS_update (stats,
4910 gettext_noop ("# HELLOs ignored due to high load"),
4911 1,
4912 GNUNET_NO);
4913#if DEBUG_TRANSPORT_HELLO
4914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4915 "Ignoring `%s' for `%4s', load too high.\n",
4916 "HELLO",
4917 GNUNET_i2s (&target));
4918#endif
4919 return GNUNET_OK;
4920 }
4921
4922
4807 chvc = chvc_head; 4923 chvc = chvc_head;
4808 while (NULL != chvc) 4924 while (NULL != chvc)
4809 { 4925 {
@@ -4819,7 +4935,7 @@ process_hello (struct TransportPlugin *plugin,
4819#endif 4935#endif
4820 return GNUNET_OK; /* validation already pending */ 4936 return GNUNET_OK; /* validation already pending */
4821 } 4937 }
4822 if (GNUNET_HELLO_size(hello) == GNUNET_HELLO_size (chvc->hello)) 4938 if (GNUNET_HELLO_size (hello) == GNUNET_HELLO_size (chvc->hello))
4823 GNUNET_break (0 != memcmp (hello, chvc->hello, 4939 GNUNET_break (0 != memcmp (hello, chvc->hello,
4824 GNUNET_HELLO_size(hello))); 4940 GNUNET_HELLO_size(hello)));
4825 chvc = chvc->next; 4941 chvc = chvc->next;
@@ -5034,11 +5150,11 @@ disconnect_neighbour (struct NeighbourList *n, int check)
5034 * in response to the peer by any means necessary. 5150 * in response to the peer by any means necessary.
5035 */ 5151 */
5036static int 5152static int
5037handle_ping(void *cls, const struct GNUNET_MessageHeader *message, 5153handle_ping (void *cls, const struct GNUNET_MessageHeader *message,
5038 const struct GNUNET_PeerIdentity *peer, 5154 const struct GNUNET_PeerIdentity *peer,
5039 struct Session *session, 5155 struct Session *session,
5040 const char *sender_address, 5156 const char *sender_address,
5041 uint16_t sender_address_len) 5157 uint16_t sender_address_len)
5042{ 5158{
5043 struct TransportPlugin *plugin = cls; 5159 struct TransportPlugin *plugin = cls;
5044 struct SessionHeader *session_header = (struct SessionHeader*) session; 5160 struct SessionHeader *session_header = (struct SessionHeader*) session;
@@ -5051,6 +5167,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5051 const char *addr; 5167 const char *addr;
5052 size_t alen; 5168 size_t alen;
5053 size_t slen; 5169 size_t slen;
5170 int did_pong;
5054 5171
5055 if (ntohs (message->size) < sizeof (struct TransportPingMessage)) 5172 if (ntohs (message->size) < sizeof (struct TransportPingMessage))
5056 { 5173 {
@@ -5103,6 +5220,19 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5103 GNUNET_i2s (peer)); 5220 GNUNET_i2s (peer));
5104 return GNUNET_SYSERR; 5221 return GNUNET_SYSERR;
5105 } 5222 }
5223 /* FIXME-urg: the use of 'sender_address' in the code below is doubly-wrong:
5224 1) it is NULL when we need to have a real value
5225 2) it is documented to be the address of the sender (source-IP), where
5226 what we actually want is our LISTEN IP (what we 'bound' to); which we don't even
5227 have...
5228 */
5229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5230 "Creating PONG indicating that we received a connection at our address `%s' from `%s'.\n",
5231 a2s (plugin->short_name,
5232 sender_address,
5233 sender_address_len),
5234 GNUNET_i2s (peer));
5235
5106 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen); 5236 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen);
5107 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen); 5237 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen);
5108 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); 5238 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
@@ -5229,6 +5359,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5229 } 5359 }
5230 n = find_neighbour(peer); 5360 n = find_neighbour(peer);
5231 GNUNET_assert (n != NULL); 5361 GNUNET_assert (n != NULL);
5362 did_pong = GNUNET_NO;
5232 /* first try reliable response transmission */ 5363 /* first try reliable response transmission */
5233 rl = n->plugins; 5364 rl = n->plugins;
5234 while (rl != NULL) 5365 while (rl != NULL)
@@ -5248,6 +5379,9 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5248 GNUNET_SYSERR, 5379 GNUNET_SYSERR,
5249 NULL, NULL)) 5380 NULL, NULL))
5250 { 5381 {
5382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5383 "Transmitted PONG to `%s' via reliable mechanism\n",
5384 GNUNET_i2s (peer));
5251 /* done! */ 5385 /* done! */
5252 GNUNET_STATISTICS_update (stats, 5386 GNUNET_STATISTICS_update (stats,
5253 gettext_noop ("# PONGs unicast via reliable transport"), 5387 gettext_noop ("# PONGs unicast via reliable transport"),
@@ -5256,6 +5390,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5256 GNUNET_free (pong); 5390 GNUNET_free (pong);
5257 return GNUNET_OK; 5391 return GNUNET_OK;
5258 } 5392 }
5393 did_pong = GNUNET_YES;
5259 fal = fal->next; 5394 fal = fal->next;
5260 } 5395 }
5261 rl = rl->next; 5396 rl = rl->next;
@@ -5271,6 +5406,13 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5271 fal = rl->addresses; 5406 fal = rl->addresses;
5272 while (fal != NULL) 5407 while (fal != NULL)
5273 { 5408 {
5409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5410 "Transmitting PONG to `%s' via unreliable mechanism `%s':%s\n",
5411 GNUNET_i2s (peer),
5412 a2s (rl->plugin->short_name,
5413 fal->addr,
5414 fal->addrlen),
5415 rl->plugin->short_name);
5274 transmit_to_peer(NULL, fal, 5416 transmit_to_peer(NULL, fal,
5275 TRANSPORT_PONG_PRIORITY, 5417 TRANSPORT_PONG_PRIORITY,
5276 HELLO_VERIFICATION_TIMEOUT, 5418 HELLO_VERIFICATION_TIMEOUT,
@@ -5278,11 +5420,16 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
5278 ntohs(pong->header.size), 5420 ntohs(pong->header.size),
5279 GNUNET_YES, 5421 GNUNET_YES,
5280 n); 5422 n);
5423 did_pong = GNUNET_YES;
5281 fal = fal->next; 5424 fal = fal->next;
5282 } 5425 }
5283 rl = rl->next; 5426 rl = rl->next;
5284 } 5427 }
5285 GNUNET_free(pong); 5428 GNUNET_free(pong);
5429 if (GNUNET_YES != did_pong)
5430 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5431 _("Could not send PONG to `%s': no address available\n"),
5432 GNUNET_i2s (peer));
5286 return GNUNET_OK; 5433 return GNUNET_OK;
5287} 5434}
5288 5435
@@ -5441,6 +5588,8 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
5441 break; 5588 break;
5442 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: 5589 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
5443 handle_ping (plugin, message, peer, session, sender_address, sender_address_len); 5590 handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
5591 if (! n->received_pong)
5592 transmit_plain_ping (n);
5444 break; 5593 break;
5445 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: 5594 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
5446 handle_pong (plugin, message, peer, sender_address, sender_address_len); 5595 handle_pong (plugin, message, peer, sender_address, sender_address_len);
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index a8eee970c..af9538a68 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -38,9 +38,9 @@
38#include "gnunet_transport_plugin.h" 38#include "gnunet_transport_plugin.h"
39#include "transport.h" 39#include "transport.h"
40 40
41#define DEBUG_TCP GNUNET_YES 41#define DEBUG_TCP GNUNET_NO
42 42
43#define DEBUG_TCP_NAT GNUNET_YES 43#define DEBUG_TCP_NAT GNUNET_NO
44 44
45 45
46/** 46/**
@@ -1517,7 +1517,6 @@ handle_tcp_nat_probe (void *cls,
1517 } 1517 }
1518 1518
1519 tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *)message; 1519 tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *)message;
1520
1521 if (0 == memcmp (&tcp_nat_probe->clientIdentity, 1520 if (0 == memcmp (&tcp_nat_probe->clientIdentity,
1522 plugin->env->my_identity, 1521 plugin->env->my_identity,
1523 sizeof (struct GNUNET_PeerIdentity))) 1522 sizeof (struct GNUNET_PeerIdentity)))
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index ac818d557..ae56c939f 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -37,7 +37,7 @@
37#include "transport.h" 37#include "transport.h"
38#include "transport-testing.h" 38#include "transport-testing.h"
39 39
40#define VERBOSE GNUNET_YES 40#define VERBOSE GNUNET_NO
41 41
42#define VERBOSE_ARM GNUNET_NO 42#define VERBOSE_ARM GNUNET_NO
43 43
@@ -122,16 +122,57 @@ static void
122stop_arm (struct PeerContext *p) 122stop_arm (struct PeerContext *p)
123{ 123{
124#if START_ARM 124#if START_ARM
125 if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM)) 125 if (NULL != p->arm_proc)
126 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); 126 {
127 GNUNET_OS_process_wait (p->arm_proc); 127 if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
128 GNUNET_OS_process_close (p->arm_proc); 128 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
129 p->arm_proc = NULL; 129 GNUNET_OS_process_wait (p->arm_proc);
130 GNUNET_OS_process_close (p->arm_proc);
131 p->arm_proc = NULL;
132 }
130#endif 133#endif
131 GNUNET_CONFIGURATION_destroy (p->cfg); 134 GNUNET_CONFIGURATION_destroy (p->cfg);
132} 135}
133 136
134 137
138
139
140static void
141exchange_hello_last (void *cls,
142 const struct GNUNET_MessageHeader *message)
143{
144 struct PeerContext *me = cls;
145
146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
147 "Exchanging HELLO of size %d with peer (%s)!\n",
148 (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
149 GNUNET_i2s (&me->id));
150 GNUNET_assert (message != NULL);
151 GNUNET_assert (GNUNET_OK ==
152 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
153 message, &me->id));
154 GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
155}
156
157
158static void
159exchange_hello (void *cls,
160 const struct GNUNET_MessageHeader *message)
161{
162 struct PeerContext *me = cls;
163
164 GNUNET_assert (message != NULL);
165 GNUNET_assert (GNUNET_OK ==
166 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
167 message, &me->id));
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
169 "Exchanging HELLO of size %d from peer %s!\n",
170 (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
171 GNUNET_i2s (&me->id));
172 GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
173}
174
175
135static void 176static void
136end_badly () 177end_badly ()
137{ 178{
@@ -139,8 +180,15 @@ end_badly ()
139 GNUNET_break (0); 180 GNUNET_break (0);
140 181
141 if (th != NULL) 182 if (th != NULL)
142 GNUNET_TRANSPORT_notify_transmit_ready_cancel(th); 183 {
143 th = NULL; 184 GNUNET_TRANSPORT_notify_transmit_ready_cancel(th);
185 th = NULL;
186 }
187 else
188 {
189 GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
190 GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
191 }
144 192
145 GNUNET_TRANSPORT_disconnect (p1.th); 193 GNUNET_TRANSPORT_disconnect (p1.th);
146 GNUNET_TRANSPORT_disconnect (p2.th); 194 GNUNET_TRANSPORT_disconnect (p2.th);
@@ -199,44 +247,6 @@ notify_ready (void *cls, size_t size, void *buf)
199 247
200 248
201static void 249static void
202exchange_hello_last (void *cls,
203 const struct GNUNET_MessageHeader *message)
204{
205 struct PeerContext *me = cls;
206
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Exchanging HELLO of size %d with peer (%s)!\n",
209 (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
210 GNUNET_i2s (&me->id));
211 GNUNET_assert (message != NULL);
212 GNUNET_assert (GNUNET_OK ==
213 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
214 message, &me->id));
215 GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
216}
217
218
219
220static void
221exchange_hello (void *cls,
222 const struct GNUNET_MessageHeader *message)
223{
224 struct PeerContext *me = cls;
225
226 GNUNET_assert (message != NULL);
227 GNUNET_assert (GNUNET_OK ==
228 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
229 message, &me->id));
230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 "Exchanging HELLO of size %d from peer %s!\n",
232 (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
233 GNUNET_i2s (&me->id));
234 GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
235}
236
237
238
239static void
240notify_connect (void *cls, 250notify_connect (void *cls,
241 const struct GNUNET_PeerIdentity *peer, 251 const struct GNUNET_PeerIdentity *peer,
242 const struct GNUNET_TRANSPORT_ATS_Information *ats, 252 const struct GNUNET_TRANSPORT_ATS_Information *ats,
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
index d6b0cc8ab..4db080cda 100644
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ b/src/transport/test_transport_api_tcp_peer1.conf
@@ -31,7 +31,7 @@ MINIMUM-FRIENDS = 0
31 31
32[transport] 32[transport]
33PLUGINS = tcp 33PLUGINS = tcp
34DEBUG = YES 34#DEBUG = YES
35#PREFIX = xterm -T transport2 -e gdb --command=cmd --args 35#PREFIX = xterm -T transport2 -e gdb --command=cmd --args
36#PREFIX = valgrind --tool=memcheck --leak-check=full --log-file=transport%p.vg 36#PREFIX = valgrind --tool=memcheck --leak-check=full --log-file=transport%p.vg
37ACCEPT_FROM6 = ::1; 37ACCEPT_FROM6 = ::1;
diff --git a/src/transport/transport.h b/src/transport/transport.h
index 504cbe62b..0e4fba731 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -36,7 +36,7 @@
36#define ATS_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3) 36#define ATS_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
37#define ATS_MAX_ITERATIONS INT_MAX 37#define ATS_MAX_ITERATIONS INT_MAX
38 38
39#define DEBUG_TRANSPORT GNUNET_YES 39#define DEBUG_TRANSPORT 3
40 40
41#define DEBUG_TRANSPORT_TIMEOUT GNUNET_NO 41#define DEBUG_TRANSPORT_TIMEOUT GNUNET_NO
42 42
diff --git a/src/util/connection.c b/src/util/connection.c
index ccdaaa9ed..200f7aed6 100644
--- a/src/util/connection.c
+++ b/src/util/connection.c
@@ -1028,6 +1028,9 @@ GNUNET_CONNECTION_create_from_sockaddr (int af_family,
1028 { 1028 {
1029 /* maybe refused / unsupported address, try next */ 1029 /* maybe refused / unsupported address, try next */
1030 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect"); 1030 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
1031 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1032 _("Attempt to connect to `%s' failed\n"),
1033 GNUNET_a2s (serv_addr, addrlen));
1031 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s)); 1034 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
1032 return NULL; 1035 return NULL;
1033 } 1036 }