aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2014-01-16 17:02:54 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2014-01-16 17:02:54 +0000
commit2134d1a1eaa421d42e93ce0be1f718758c4a6e4b (patch)
tree5299be8050b9be0610fce0febcf65a66ca4a4d37 /src
parent5b7924338e828c773d2179a7b7cfad6ab5074c4f (diff)
downloadgnunet-2134d1a1eaa421d42e93ce0be1f718758c4a6e4b.tar.gz
gnunet-2134d1a1eaa421d42e93ce0be1f718758c4a6e4b.zip
perform blacklist before address switch
this commit adds the blacklist check before address switch in the next step the old blacklist check has to be removed
Diffstat (limited to 'src')
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c381
1 files changed, 244 insertions, 137 deletions
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index ad649ec0a..871b6c2cf 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -463,6 +463,16 @@ static struct BlackListCheckContext *bc_head;
463static struct BlackListCheckContext *bc_tail; 463static struct BlackListCheckContext *bc_tail;
464 464
465/** 465/**
466 * List of pending blacklist checks: head
467 */
468static struct BlacklistCheckSwitchContext *pending_bc_head;
469
470/**
471 * List of pending blacklist checks: tail
472 */
473static struct BlacklistCheckSwitchContext *pending_bc_tail;
474
475/**
466 * Closure for #connect_notify_cb, #disconnect_notify_cb and #neighbour_change_cb 476 * Closure for #connect_notify_cb, #disconnect_notify_cb and #neighbour_change_cb
467 */ 477 */
468static void *callback_cls; 478static void *callback_cls;
@@ -2240,94 +2250,75 @@ GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
2240 return GNUNET_OK; 2250 return GNUNET_OK;
2241} 2251}
2242 2252
2253struct BlacklistCheckSwitchContext
2254{
2255 struct BlacklistCheckSwitchContext *prev;
2256 struct BlacklistCheckSwitchContext *next;
2243 2257
2244/** 2258 struct GNUNET_HELLO_Address *address;
2245 * For an existing neighbour record, set the active connection to 2259 struct Session *session;
2246 * use the given address. 2260 struct GNUNET_ATS_Information *ats;
2247 * 2261 uint32_t ats_count;
2248 * @param peer identity of the peer to switch the address for 2262
2249 * @param address address of the other peer, NULL if other peer 2263 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
2250 * connected to us 2264 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
2251 * @param session session to use (or NULL) 2265};
2252 * @param ats performance data 2266
2253 * @param ats_count number of entries in ats 2267static void
2254 * @param bandwidth_in inbound quota to be used when connection is up, 2268switch_address_bl_check_cont (void *cls,
2255 * 0 to disconnect from peer 2269 const struct GNUNET_PeerIdentity *peer, int result)
2256 * @param bandwidth_out outbound quota to be used when connection is up,
2257 * 0 to disconnect from peer
2258 */
2259void
2260GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2261 const struct GNUNET_HELLO_Address *address,
2262 struct Session *session,
2263 const struct GNUNET_ATS_Information *ats,
2264 uint32_t ats_count,
2265 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2266 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2267{ 2270{
2268 struct NeighbourMapEntry *n; 2271 struct BlacklistCheckSwitchContext *blc_ctx = cls;
2269 struct GNUNET_TRANSPORT_PluginFunctions *papi; 2272 struct GNUNET_TRANSPORT_PluginFunctions *papi;
2273 struct NeighbourMapEntry *n;
2270 2274
2271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2272 "ATS has decided on an address for peer %s\n",
2273 GNUNET_i2s (peer));
2274 GNUNET_assert (NULL != address->transport_name);
2275 if (NULL == (n = lookup_neighbour (peer)))
2276 {
2277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2278 "Peer %s is unknown, suggestion ignored\n",
2279 GNUNET_i2s (peer));
2280 return;
2281 }
2282 2275
2283 /* Obtain an session for this address from plugin */ 2276 if ( (NULL == (n = lookup_neighbour (peer))) || (result == GNUNET_NO) ||
2284 if (NULL == (papi = GST_plugins_find (address->transport_name))) 2277 (NULL == (papi = GST_plugins_find (blc_ctx->address->transport_name))) )
2285 {
2286 /* we don't have the plugin for this address */
2287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2288 "Plugin `%s' is unknown, suggestion for peer %s ignored\n",
2289 address->transport_name,
2290 GNUNET_i2s (peer));
2291 GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
2292 return;
2293 }
2294 if ((NULL == session) &&
2295 (GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)))
2296 { 2278 {
2297 /* This is a inbound address and we do not have a session to use! */ 2279 if (NULL == n)
2298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2280 {
2299 "Inbound address without session `%s'! Destroying address...\n", 2281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2300 GST_plugins_a2s (address)); 2282 "Peer %s is unknown, suggestion ignored\n",
2301 GNUNET_ATS_address_destroyed (GST_ats, address, NULL); 2283 GNUNET_i2s (peer));
2284 }
2285 if (result == GNUNET_NO)
2286 {
2287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2288 "Blacklist denied to switch to suggested address `%s' sesion %p for peer `%s'\n",
2289 GST_plugins_a2s (blc_ctx->address),
2290 blc_ctx->session,
2291 GNUNET_i2s (&blc_ctx->address->peer));
2292 }
2293 /* Delete address (or session if existing) in ATS */
2294 GNUNET_ATS_address_destroyed (GST_ats, blc_ctx->address, blc_ctx->session);
2295
2296 GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx);
2297 GNUNET_HELLO_address_free(blc_ctx->address);
2298 GNUNET_free_non_null (blc_ctx->ats);
2299 GNUNET_free (blc_ctx);
2302 return; 2300 return;
2303 } 2301 }
2304 2302
2305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2306 "ATS tells us to switch to %s address '%s' session %p for " 2304 "Blacklist accepted to switch to suggested address `%s' for peer `%s'\n",
2307 "peer `%s' in state %s/%d (quota in/out %u %u )\n", 2305 GST_plugins_a2s (blc_ctx->address),
2308 GNUNET_HELLO_address_check_option (address, 2306 blc_ctx->session,
2309 GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "", 2307 GNUNET_i2s (&blc_ctx->address->peer));
2310 GST_plugins_a2s (address),
2311 session,
2312 GNUNET_i2s (peer),
2313 GNUNET_TRANSPORT_ps2s (n->state),
2314 n->send_connect_ack,
2315 ntohl (bandwidth_in.value__),
2316 ntohl (bandwidth_out.value__));
2317 2308
2318 if (NULL == session) 2309 if (NULL == blc_ctx->session)
2319 { 2310 {
2320 session = papi->get_session (papi->cls, address); 2311 blc_ctx->session = papi->get_session (papi->cls, blc_ctx->address);
2321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2322 "Obtained new session for peer `%s' and address '%s': %p\n", 2313 "Obtained new session for peer `%s' and address '%s': %p\n",
2323 GNUNET_i2s (&address->peer), GST_plugins_a2s (address), session); 2314 GNUNET_i2s (&blc_ctx->address->peer), GST_plugins_a2s (blc_ctx->address), blc_ctx->session);
2324 } 2315 }
2325 if (NULL == session) 2316 if (NULL == blc_ctx->session)
2326 { 2317 {
2327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2328 "Failed to obtain new session for peer `%s' and address '%s'\n", 2319 "Failed to obtain new session for peer `%s' and address '%s'\n",
2329 GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); 2320 GNUNET_i2s (&blc_ctx->address->peer), GST_plugins_a2s (blc_ctx->address));
2330 GNUNET_ATS_address_destroyed (GST_ats, address, NULL); 2321 GNUNET_ATS_address_destroyed (GST_ats, blc_ctx->address, NULL);
2331 return; 2322 return;
2332 } 2323 }
2333 switch (n->state) 2324 switch (n->state)
@@ -2337,102 +2328,101 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2337 free_neighbour (n, GNUNET_NO); 2328 free_neighbour (n, GNUNET_NO);
2338 return; 2329 return;
2339 case GNUNET_TRANSPORT_PS_INIT_ATS: 2330 case GNUNET_TRANSPORT_PS_INIT_ATS:
2340 set_primary_address (n, address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2331 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2341 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2332 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2342 check_blacklist (&n->id, 2333 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_BLACKLIST,
2343 n->connect_ack_timestamp, 2334 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2344 address, session); 2335 check_blacklist (&n->id, n->connect_ack_timestamp,
2336 blc_ctx->address, blc_ctx->session);
2345 break; 2337 break;
2346 case GNUNET_TRANSPORT_PS_INIT_BLACKLIST: 2338 case GNUNET_TRANSPORT_PS_INIT_BLACKLIST:
2347 /* ATS suggests a different address, switch again */ 2339 /* ATS suggests a different address, switch again */
2348 set_primary_address (n, 2340 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2349 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2341 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2350 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2342 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2351 check_blacklist (&n->id, 2343 check_blacklist (&n->id, n->connect_ack_timestamp,
2352 n->connect_ack_timestamp, 2344 blc_ctx->address, blc_ctx->session);
2353 address, session);
2354 break; 2345 break;
2355 case GNUNET_TRANSPORT_PS_CONNECT_SENT: 2346 case GNUNET_TRANSPORT_PS_CONNECT_SENT:
2356 /* ATS suggests a different address, switch again */ 2347 /* ATS suggests a different address, switch again */
2357 set_primary_address (n, address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2348 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2358 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2349 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2359 check_blacklist (&n->id, 2350 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_BLACKLIST,
2360 n->connect_ack_timestamp, 2351 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2361 address, session); 2352 check_blacklist (&n->id, n->connect_ack_timestamp,
2353 blc_ctx->address, blc_ctx->session);
2362 break; 2354 break;
2363 case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: 2355 case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS:
2364 set_primary_address (n, 2356 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2365 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2357 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2366 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2358 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST,
2367 check_blacklist (&n->id, 2359 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2368 n->connect_ack_timestamp, 2360 check_blacklist (&n->id, n->connect_ack_timestamp,
2369 address, session); 2361 blc_ctx->address, blc_ctx->session);
2370 break; 2362 break;
2371 case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST_INBOUND: 2363 case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST_INBOUND:
2372 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2364 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2373 check_blacklist (&n->id, 2365 check_blacklist (&n->id, n->connect_ack_timestamp,
2374 n->connect_ack_timestamp, 2366 blc_ctx->address, blc_ctx->session);
2375 address, session);
2376 break; 2367 break;
2377 case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST: 2368 case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST:
2378 case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: 2369 case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK:
2379 /* ATS asks us to switch while we were trying to connect; switch to new 2370 /* ATS asks us to switch while we were trying to connect; switch to new
2380 address and check blacklist again */ 2371 address and check blacklist again */
2381 set_primary_address (n, 2372 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2382 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2373 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2383 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2374 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST,
2384 check_blacklist (&n->id, 2375 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2385 n->connect_ack_timestamp, 2376 check_blacklist (&n->id, n->connect_ack_timestamp,
2386 address, session); 2377 blc_ctx->address, blc_ctx->session);
2387 break; 2378 break;
2388 case GNUNET_TRANSPORT_PS_CONNECTED: 2379 case GNUNET_TRANSPORT_PS_CONNECTED:
2389 GNUNET_assert (NULL != n->primary_address.address); 2380 GNUNET_assert (NULL != n->primary_address.address);
2390 GNUNET_assert (NULL != n->primary_address.session); 2381 GNUNET_assert (NULL != n->primary_address.session);
2391 if (n->primary_address.session == session) 2382 if (n->primary_address.session == blc_ctx->session)
2392 { 2383 {
2393 /* not an address change, just a quota change */ 2384 /* not an address change, just a quota change */
2394 set_primary_address (n, 2385 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2395 address, session, bandwidth_in, bandwidth_out, GNUNET_YES); 2386 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_YES);
2396 break; 2387 break;
2397 } 2388 }
2398 /* ATS asks us to switch a life connection; see if we can get 2389 /* ATS asks us to switch a life connection; see if we can get
2399 a CONNECT_ACK on it before we actually do this! */ 2390 a CONNECT_ACK on it before we actually do this! */
2400 set_state (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST); 2391 set_state (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST);
2401 set_alternative_address (n, address, session, bandwidth_in, bandwidth_out); 2392 set_alternative_address (n, blc_ctx->address, blc_ctx->session,
2402 check_blacklist (&n->id, 2393 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out);
2403 GNUNET_TIME_absolute_get (), 2394 check_blacklist (&n->id, GNUNET_TIME_absolute_get (),
2404 address, session); 2395 blc_ctx->address, blc_ctx->session);
2405 break; 2396 break;
2406 case GNUNET_TRANSPORT_PS_RECONNECT_ATS: 2397 case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
2407 set_primary_address (n, 2398 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2408 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2399 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2409 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2400 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST,
2410 check_blacklist (&n->id, 2401 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2411 n->connect_ack_timestamp, 2402 check_blacklist (&n->id, n->connect_ack_timestamp,
2412 address, session); 2403 blc_ctx->address, blc_ctx->session);
2413 break; 2404 break;
2414 case GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST: 2405 case GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST:
2415 /* ATS asks us to switch while we were trying to reconnect; switch to new 2406 /* ATS asks us to switch while we were trying to reconnect; switch to new
2416 address and check blacklist again */ 2407 address and check blacklist again */
2417 set_primary_address (n, 2408 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2418 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2409 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2419 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2410 set_timeout (n, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2420 check_blacklist (&n->id, 2411 check_blacklist (&n->id, n->connect_ack_timestamp,
2421 n->connect_ack_timestamp, 2412 blc_ctx->address, blc_ctx->session);
2422 address, session);
2423 break; 2413 break;
2424 case GNUNET_TRANSPORT_PS_RECONNECT_SENT: 2414 case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
2425 /* ATS asks us to switch while we were trying to reconnect; switch to new 2415 /* ATS asks us to switch while we were trying to reconnect; switch to new
2426 address and check blacklist again */ 2416 address and check blacklist again */
2427 set_primary_address (n, 2417 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2428 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2418 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2429 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST, GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT)); 2419 set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST,
2430 check_blacklist (&n->id, 2420 GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT));
2431 n->connect_ack_timestamp, 2421 check_blacklist (&n->id, n->connect_ack_timestamp,
2432 address, session); 2422 blc_ctx->address, blc_ctx->session);
2433 break; 2423 break;
2434 case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST: 2424 case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST:
2435 if (n->primary_address.session == session) 2425 if (n->primary_address.session == blc_ctx->session)
2436 { 2426 {
2437 /* ATS switches back to still-active session */ 2427 /* ATS switches back to still-active session */
2438 set_state(n, GNUNET_TRANSPORT_PS_CONNECTED); 2428 set_state(n, GNUNET_TRANSPORT_PS_CONNECTED);
@@ -2440,14 +2430,13 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2440 break; 2430 break;
2441 } 2431 }
2442 /* ATS asks us to switch a life connection, update blacklist check */ 2432 /* ATS asks us to switch a life connection, update blacklist check */
2443 set_primary_address (n, 2433 set_primary_address (n, blc_ctx->address, blc_ctx->session,
2444 address, session, bandwidth_in, bandwidth_out, GNUNET_NO); 2434 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO);
2445 check_blacklist (&n->id, 2435 check_blacklist (&n->id, GNUNET_TIME_absolute_get (),
2446 GNUNET_TIME_absolute_get (), 2436 blc_ctx->address, blc_ctx->session);
2447 address, session);
2448 break; 2437 break;
2449 case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: 2438 case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT:
2450 if (n->primary_address.session == session) 2439 if (n->primary_address.session == blc_ctx->session)
2451 { 2440 {
2452 /* ATS switches back to still-active session */ 2441 /* ATS switches back to still-active session */
2453 free_address (&n->alternative_address); 2442 free_address (&n->alternative_address);
@@ -2456,10 +2445,10 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2456 } 2445 }
2457 /* ATS asks us to switch a life connection, update blacklist check */ 2446 /* ATS asks us to switch a life connection, update blacklist check */
2458 set_state (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST); 2447 set_state (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST);
2459 set_alternative_address (n, address, session, bandwidth_in, bandwidth_out); 2448 set_alternative_address (n, blc_ctx->address, blc_ctx->session,
2460 check_blacklist (&n->id, 2449 blc_ctx->bandwidth_in, blc_ctx->bandwidth_out);
2461 GNUNET_TIME_absolute_get (), 2450 check_blacklist (&n->id, GNUNET_TIME_absolute_get (),
2462 address, session); 2451 blc_ctx->address, blc_ctx->session);
2463 break; 2452 break;
2464 case GNUNET_TRANSPORT_PS_DISCONNECT: 2453 case GNUNET_TRANSPORT_PS_DISCONNECT:
2465 /* not going to switch addresses while disconnecting */ 2454 /* not going to switch addresses while disconnecting */
@@ -2474,6 +2463,109 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2474 GNUNET_break (0); 2463 GNUNET_break (0);
2475 break; 2464 break;
2476 } 2465 }
2466
2467 GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx);
2468 GNUNET_HELLO_address_free(blc_ctx->address);
2469 GNUNET_free_non_null (blc_ctx->ats);
2470 GNUNET_free (blc_ctx);
2471 return;
2472}
2473
2474
2475/**
2476 * For the given peer, switch to this address.
2477 *
2478 * Before accepting this addresses and actively using it, a blacklist check
2479 * is performed. If this blacklist check fails the address will be destroyed.
2480 *
2481 * @param peer identity of the peer to switch the address for
2482 * @param address address of the other peer,
2483 * @param session session to use or NULL if transport should initiate a session
2484 * @param ats performance data
2485 * @param ats_count number of entries in ats
2486 * @param bandwidth_in inbound quota to be used when connection is up,
2487 * 0 to disconnect from peer
2488 * @param bandwidth_out outbound quota to be used when connection is up,
2489 * 0 to disconnect from peer
2490 */
2491void
2492GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
2493 const struct GNUNET_HELLO_Address *address,
2494 struct Session *session,
2495 const struct GNUNET_ATS_Information *ats,
2496 uint32_t ats_count,
2497 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
2498 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
2499{
2500 struct NeighbourMapEntry *n;
2501 struct GNUNET_TRANSPORT_PluginFunctions *papi;
2502 struct BlacklistCheckSwitchContext *blc_ctx;
2503 int c;
2504
2505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2506 "ATS has decided on an address for peer %s\n",
2507 GNUNET_i2s (peer));
2508 GNUNET_assert (NULL != address->transport_name);
2509 if (NULL == (n = lookup_neighbour (peer)))
2510 {
2511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2512 "Peer %s is unknown, suggestion ignored\n",
2513 GNUNET_i2s (peer));
2514 return;
2515 }
2516
2517 /* Obtain an session for this address from plugin */
2518 if (NULL == (papi = GST_plugins_find (address->transport_name)))
2519 {
2520 /* we don't have the plugin for this address */
2521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2522 "Plugin `%s' is unknown, suggestion for peer %s ignored\n",
2523 address->transport_name,
2524 GNUNET_i2s (peer));
2525 GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
2526 return;
2527 }
2528 if ((NULL == session) &&
2529 (GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)))
2530 {
2531 /* This is a inbound address and we do not have a session to use! */
2532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2533 "Inbound address without session `%s'! Destroying address...\n",
2534 GST_plugins_a2s (address));
2535 GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
2536 return;
2537 }
2538
2539 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2540 "ATS tells us to switch to %s address '%s' session %p for "
2541 "peer `%s' in state %s/%d (quota in/out %u %u )\n",
2542 GNUNET_HELLO_address_check_option (address,
2543 GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "",
2544 GST_plugins_a2s (address), session, GNUNET_i2s (peer),
2545 GNUNET_TRANSPORT_ps2s (n->state), n->send_connect_ack,
2546 ntohl (bandwidth_in.value__), ntohl (bandwidth_out.value__));
2547
2548 /* Perform blacklist check */
2549 blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
2550 blc_ctx->address = GNUNET_HELLO_address_copy (address);
2551 blc_ctx->session = session;
2552 blc_ctx->bandwidth_in = bandwidth_in;
2553 blc_ctx->bandwidth_out = bandwidth_out;
2554 blc_ctx->ats_count = ats_count;
2555 blc_ctx->ats = NULL;
2556 if (ats_count > 0)
2557 {
2558 blc_ctx->ats = GNUNET_malloc (ats_count * sizeof (struct GNUNET_ATS_Information));
2559 for (c = 0; c < ats_count; c++)
2560 {
2561 blc_ctx->ats[c].type = ats[c].type;
2562 blc_ctx->ats[c].value = ats[c].value;
2563 }
2564 }
2565
2566 GNUNET_CONTAINER_DLL_insert (pending_bc_head, pending_bc_tail, blc_ctx);
2567 GST_blacklist_test_allowed (peer, address->transport_name,
2568 &switch_address_bl_check_cont, blc_ctx);
2477} 2569}
2478 2570
2479 2571
@@ -3549,6 +3641,9 @@ disconnect_all_neighbours (void *cls,
3549void 3641void
3550GST_neighbours_stop () 3642GST_neighbours_stop ()
3551{ 3643{
3644 struct BlacklistCheckSwitchContext *cur;
3645 struct BlacklistCheckSwitchContext *next;
3646
3552 if (NULL == neighbours) 3647 if (NULL == neighbours)
3553 return; 3648 return;
3554 if (GNUNET_SCHEDULER_NO_TASK != util_transmission_tk) 3649 if (GNUNET_SCHEDULER_NO_TASK != util_transmission_tk)
@@ -3561,6 +3656,18 @@ GST_neighbours_stop ()
3561 &disconnect_all_neighbours, 3656 &disconnect_all_neighbours,
3562 NULL); 3657 NULL);
3563 GNUNET_CONTAINER_multipeermap_destroy (neighbours); 3658 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
3659
3660 next = pending_bc_head;
3661 for (cur = next; NULL != cur; cur = next )
3662 {
3663 next = cur->next;
3664
3665 GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, cur);
3666 GNUNET_HELLO_address_free (cur->address);
3667 GNUNET_free_non_null (cur->ats);
3668 GNUNET_free (cur);
3669 }
3670
3564 neighbours = NULL; 3671 neighbours = NULL;
3565 callback_cls = NULL; 3672 callback_cls = NULL;
3566 connect_notify_cb = NULL; 3673 connect_notify_cb = NULL;