aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-04 08:13:15 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-04 08:13:15 +0000
commit4be3bd14be40dd9686479e43591159fb26d9b0ea (patch)
treef0f377444462d4ece9893bd74632efe29d10a404 /src/transport/gnunet-service-transport.c
parentc7ad60c5fd958a4f5b599c22eebc1c4a731d9b52 (diff)
downloadgnunet-4be3bd14be40dd9686479e43591159fb26d9b0ea.tar.gz
gnunet-4be3bd14be40dd9686479e43591159fb26d9b0ea.zip
minor bugfixes, switch neighbour list to hash map
Diffstat (limited to 'src/transport/gnunet-service-transport.c')
-rw-r--r--src/transport/gnunet-service-transport.c614
1 files changed, 350 insertions, 264 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 2d0e25a51..8dc826e50 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -439,17 +439,12 @@ struct ReadyList
439 439
440 440
441/** 441/**
442 * Entry in linked list of all of our current neighbours. 442 * Entry in neighbours. (not a 'List' -- bad name!)
443 */ 443 */
444struct NeighbourList 444struct NeighbourList
445{ 445{
446 446
447 /** 447 /**
448 * This is a linked list.
449 */
450 struct NeighbourList *next;
451
452 /**
453 * Which of our transports is connected to this peer 448 * Which of our transports is connected to this peer
454 * and what is their status? 449 * and what is their status?
455 */ 450 */
@@ -882,7 +877,7 @@ static struct GNUNET_PEERINFO_Handle *peerinfo;
882/** 877/**
883 * All known neighbours and their HELLOs. 878 * All known neighbours and their HELLOs.
884 */ 879 */
885static struct NeighbourList *neighbours; 880static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
886 881
887/** 882/**
888 * Number of neighbours we'd like to have. 883 * Number of neighbours we'd like to have.
@@ -977,12 +972,7 @@ struct ForeignAddressList * get_preferred_ats_address (
977static struct NeighbourList * 972static struct NeighbourList *
978find_neighbour (const struct GNUNET_PeerIdentity *key) 973find_neighbour (const struct GNUNET_PeerIdentity *key)
979{ 974{
980 struct NeighbourList *head = neighbours; 975 return GNUNET_CONTAINER_multihashmap_get (neighbours, &key->hashPubKey);
981
982 while ((head != NULL) &&
983 (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
984 head = head->next;
985 return head;
986} 976}
987 977
988static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , int ats_index) 978static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , int ats_index)
@@ -2185,6 +2175,34 @@ address_generator (void *cls, size_t max, void *buf)
2185} 2175}
2186 2176
2187 2177
2178
2179static int
2180transmit_our_hello_if_pong (void *cls,
2181 const GNUNET_HashCode *key,
2182 void *value)
2183{
2184 struct NeighbourList *npos = value;
2185
2186 if (GNUNET_YES != npos->received_pong)
2187 return GNUNET_OK;
2188#if DEBUG_TRANSPORT
2189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2190 "Transmitting updated `%s' to neighbour `%4s'\n",
2191 "HELLO", GNUNET_i2s (&npos->id));
2192#endif
2193 GNUNET_STATISTICS_update (stats,
2194 gettext_noop ("# transmitted my HELLO to other peers"),
2195 1,
2196 GNUNET_NO);
2197 transmit_to_peer (NULL, NULL, 0,
2198 HELLO_ADDRESS_EXPIRATION,
2199 (const char *) our_hello,
2200 GNUNET_HELLO_size(our_hello),
2201 GNUNET_NO, npos);
2202 return GNUNET_OK;
2203}
2204
2205
2188/** 2206/**
2189 * Construct our HELLO message from all of the addresses of 2207 * Construct our HELLO message from all of the addresses of
2190 * all of the transports. 2208 * all of the transports.
@@ -2198,7 +2216,6 @@ refresh_hello_task (void *cls,
2198{ 2216{
2199 struct GNUNET_HELLO_Message *hello; 2217 struct GNUNET_HELLO_Message *hello;
2200 struct TransportClient *cpos; 2218 struct TransportClient *cpos;
2201 struct NeighbourList *npos;
2202 struct GeneratorContext gc; 2219 struct GeneratorContext gc;
2203 2220
2204 hello_task = GNUNET_SCHEDULER_NO_TASK; 2221 hello_task = GNUNET_SCHEDULER_NO_TASK;
@@ -2228,25 +2245,9 @@ refresh_hello_task (void *cls,
2228 GNUNET_free_non_null (our_hello); 2245 GNUNET_free_non_null (our_hello);
2229 our_hello = hello; 2246 our_hello = hello;
2230 GNUNET_PEERINFO_add_peer (peerinfo, our_hello); 2247 GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
2231 for (npos = neighbours; npos != NULL; npos = npos->next) 2248 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
2232 { 2249 &transmit_our_hello_if_pong,
2233 if (GNUNET_YES != npos->received_pong) 2250 NULL);
2234 continue;
2235#if DEBUG_TRANSPORT
2236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2237 "Transmitting updated `%s' to neighbour `%4s'\n",
2238 "HELLO", GNUNET_i2s (&npos->id));
2239#endif
2240 GNUNET_STATISTICS_update (stats,
2241 gettext_noop ("# transmitted my HELLO to other peers"),
2242 1,
2243 GNUNET_NO);
2244 transmit_to_peer (NULL, NULL, 0,
2245 HELLO_ADDRESS_EXPIRATION,
2246 (const char *) our_hello,
2247 GNUNET_HELLO_size(our_hello),
2248 GNUNET_NO, npos);
2249 }
2250} 2251}
2251 2252
2252 2253
@@ -3221,8 +3222,6 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
3221 1, 3222 1,
3222 GNUNET_NO); 3223 GNUNET_NO);
3223 n = GNUNET_malloc (sizeof (struct NeighbourList)); 3224 n = GNUNET_malloc (sizeof (struct NeighbourList));
3224 n->next = neighbours;
3225 neighbours = n;
3226 n->id = *peer; 3225 n->id = *peer;
3227 n->peer_timeout = 3226 n->peer_timeout =
3228 GNUNET_TIME_relative_to_absolute 3227 GNUNET_TIME_relative_to_absolute
@@ -3248,6 +3247,10 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
3248 n->distance = -1; 3247 n->distance = -1;
3249 n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 3248 n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3250 &neighbour_timeout_task, n); 3249 &neighbour_timeout_task, n);
3250 GNUNET_CONTAINER_multihashmap_put (neighbours,
3251 &n->id.hashPubKey,
3252 n,
3253 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3251 if (do_hello) 3254 if (do_hello)
3252 { 3255 {
3253 GNUNET_STATISTICS_update (stats, 3256 GNUNET_STATISTICS_update (stats,
@@ -3567,6 +3570,43 @@ confirm_or_drop_neighbour (void *cls,
3567} 3570}
3568 3571
3569 3572
3573struct TestConnectionContext
3574{
3575 int first;
3576
3577 struct Blacklisters *bl;
3578};
3579
3580
3581static int
3582test_connection_ok (void *cls,
3583 const GNUNET_HashCode *key,
3584 void *value)
3585{
3586 struct TestConnectionContext *tcc = cls;
3587 struct NeighbourList *n = value;
3588 struct BlacklistCheck *bc;
3589
3590
3591 bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
3592 GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
3593 bc->peer = n->id;
3594 bc->do_hello = GNUNET_NO;
3595 bc->cont = &confirm_or_drop_neighbour;
3596 bc->cont_cls = n;
3597 bc->bl_pos = tcc->bl;
3598 if (GNUNET_YES == tcc->first)
3599 {
3600 /* all would wait for the same client, no need to
3601 create more than just the first task right now */
3602 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3603 bc);
3604 tcc->first = GNUNET_NO;
3605 }
3606 return GNUNET_OK;
3607}
3608
3609
3570/** 3610/**
3571 * Handle a request to start a blacklist. 3611 * Handle a request to start a blacklist.
3572 * 3612 *
@@ -3580,8 +3620,7 @@ handle_blacklist_init (void *cls,
3580 const struct GNUNET_MessageHeader *message) 3620 const struct GNUNET_MessageHeader *message)
3581{ 3621{
3582 struct Blacklisters *bl; 3622 struct Blacklisters *bl;
3583 struct BlacklistCheck *bc; 3623 struct TestConnectionContext tcc;
3584 struct NeighbourList *n;
3585 3624
3586 bl = bl_head; 3625 bl = bl_head;
3587 while (bl != NULL) 3626 while (bl != NULL)
@@ -3599,22 +3638,11 @@ handle_blacklist_init (void *cls,
3599 GNUNET_SERVER_client_keep (client); 3638 GNUNET_SERVER_client_keep (client);
3600 GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl); 3639 GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
3601 /* confirm that all existing connections are OK! */ 3640 /* confirm that all existing connections are OK! */
3602 n = neighbours; 3641 tcc.bl = bl;
3603 while (NULL != n) 3642 tcc.first = GNUNET_YES;
3604 { 3643 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
3605 bc = GNUNET_malloc (sizeof (struct BlacklistCheck)); 3644 &test_connection_ok,
3606 GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); 3645 &tcc);
3607 bc->peer = n->id;
3608 bc->do_hello = GNUNET_NO;
3609 bc->cont = &confirm_or_drop_neighbour;
3610 bc->cont_cls = n;
3611 bc->bl_pos = bl;
3612 if (n == neighbours) /* all would wait for the same client, no need to
3613 create more than just the first task right now */
3614 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3615 bc);
3616 n = n->next;
3617 }
3618} 3646}
3619 3647
3620 3648
@@ -4852,8 +4880,6 @@ static void
4852disconnect_neighbour (struct NeighbourList *n, int check) 4880disconnect_neighbour (struct NeighbourList *n, int check)
4853{ 4881{
4854 struct ReadyList *rpos; 4882 struct ReadyList *rpos;
4855 struct NeighbourList *npos;
4856 struct NeighbourList *nprev;
4857 struct MessageQueue *mq; 4883 struct MessageQueue *mq;
4858 struct ForeignAddressList *peer_addresses; 4884 struct ForeignAddressList *peer_addresses;
4859 struct ForeignAddressList *peer_pos; 4885 struct ForeignAddressList *peer_pos;
@@ -4990,20 +5016,10 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4990 n->piter = NULL; 5016 n->piter = NULL;
4991 } 5017 }
4992 5018
4993 /* remove n from neighbours list */ 5019 GNUNET_assert (GNUNET_OK ==
4994 nprev = NULL; 5020 GNUNET_CONTAINER_multihashmap_remove (neighbours,
4995 npos = neighbours; 5021 &n->id.hashPubKey,
4996 while ((npos != NULL) && (npos != n)) 5022 n));
4997 {
4998 nprev = npos;
4999 npos = npos->next;
5000 }
5001 GNUNET_assert (npos != NULL);
5002 if (nprev == NULL)
5003 neighbours = n->next;
5004 else
5005 nprev->next = n->next;
5006
5007 /* finally, free n itself */ 5023 /* finally, free n itself */
5008 GNUNET_STATISTICS_update (stats, 5024 GNUNET_STATISTICS_update (stats,
5009 gettext_noop ("# active neighbours"), 5025 gettext_noop ("# active neighbours"),
@@ -5501,6 +5517,44 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
5501 return ret; 5517 return ret;
5502} 5518}
5503 5519
5520
5521static int
5522notify_client_about_neighbour (void *cls,
5523 const GNUNET_HashCode *key,
5524 void *value)
5525{
5526 struct TransportClient *c = cls;
5527 struct NeighbourList *n = value;
5528 struct ConnectInfoMessage * cim;
5529 uint32_t ats_count;
5530 size_t size;
5531
5532 if (GNUNET_YES != n->received_pong)
5533 return GNUNET_OK;
5534
5535 ats_count = 2;
5536 size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
5537 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
5538 cim = GNUNET_malloc (size);
5539 cim->header.size = htons (size);
5540 cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
5541 cim->ats_count = htonl(ats_count);
5542 (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
5543 (&(cim->ats))[2].value = htonl (0);
5544 if (GNUNET_YES == n->received_pong)
5545 {
5546 (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
5547 (&cim->ats)[0].value = htonl (n->distance);
5548 (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
5549 (&cim->ats)[1].value = htonl ((uint32_t) n->latency.rel_value);
5550 cim->id = n->id;
5551 transmit_to_client (c, &cim->header, GNUNET_NO);
5552 }
5553 GNUNET_free (cim);
5554 return GNUNET_OK;
5555}
5556
5557
5504/** 5558/**
5505 * Handle START-message. This is the first message sent to us 5559 * Handle START-message. This is the first message sent to us
5506 * by any client which causes us to add it to our list. 5560 * by any client which causes us to add it to our list.
@@ -5516,10 +5570,6 @@ handle_start (void *cls,
5516{ 5570{
5517 const struct StartMessage *start; 5571 const struct StartMessage *start;
5518 struct TransportClient *c; 5572 struct TransportClient *c;
5519 struct ConnectInfoMessage * cim;
5520 struct NeighbourList *n;
5521 uint32_t ats_count;
5522 size_t size;
5523 5573
5524 start = (const struct StartMessage*) message; 5574 start = (const struct StartMessage*) message;
5525#if DEBUG_TRANSPORT 5575#if DEBUG_TRANSPORT
@@ -5563,33 +5613,9 @@ handle_start (void *cls,
5563 (const struct GNUNET_MessageHeader *) our_hello, 5613 (const struct GNUNET_MessageHeader *) our_hello,
5564 GNUNET_NO); 5614 GNUNET_NO);
5565 /* tell new client about all existing connections */ 5615 /* tell new client about all existing connections */
5566 ats_count = 2; 5616 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
5567 size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information); 5617 &notify_client_about_neighbour,
5568 if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE) 5618 c);
5569 {
5570 GNUNET_break(0);
5571 }
5572 cim = GNUNET_malloc (size);
5573 cim->header.size = htons (size);
5574 cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
5575 cim->ats_count = htonl(ats_count);
5576 (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
5577 (&(cim->ats))[2].value = htonl (0);
5578 n = neighbours;
5579 while (n != NULL)
5580 {
5581 if (GNUNET_YES == n->received_pong)
5582 {
5583 (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
5584 (&cim->ats)[0].value = htonl (n->distance);
5585 (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
5586 (&cim->ats)[1].value = htonl ((uint32_t) n->latency.rel_value);
5587 cim->id = n->id;
5588 transmit_to_client (c, &cim->header, GNUNET_NO);
5589 }
5590 n = n->next;
5591 }
5592 GNUNET_free (cim);
5593 } 5619 }
5594 else 5620 else
5595 { 5621 {
@@ -5955,13 +5981,7 @@ handle_peer_address_lookup (void *cls,
5955 timeout = GNUNET_TIME_absolute_ntoh (peer_address_lookup->timeout); 5981 timeout = GNUNET_TIME_absolute_ntoh (peer_address_lookup->timeout);
5956 rtimeout = GNUNET_TIME_absolute_get_remaining (timeout); 5982 rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
5957 5983
5958 neighbor_iterator = neighbours; 5984 neighbor_iterator = find_neighbour (&peer_address_lookup->peer);
5959 while (neighbor_iterator != NULL)
5960 {
5961 if (0 == memcmp(&neighbor_iterator->id, &peer_address_lookup->peer, sizeof(struct GNUNET_PeerIdentity)))
5962 break;
5963 neighbor_iterator = neighbor_iterator->next;
5964 }
5965 5985
5966 /* Found no neighbor matching this peer id (shouldn't be possible, but...) */ 5986 /* Found no neighbor matching this peer id (shouldn't be possible, but...) */
5967 if (neighbor_iterator == NULL) 5987 if (neighbor_iterator == NULL)
@@ -6020,6 +6040,66 @@ handle_peer_address_lookup (void *cls,
6020 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 6040 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
6021} 6041}
6022 6042
6043
6044
6045static int
6046output_addresses (void *cls,
6047 const GNUNET_HashCode *key,
6048 void *value)
6049{
6050 struct GNUNET_SERVER_TransmitContext *tc = cls;
6051 struct NeighbourList *neighbor_iterator = value;
6052 struct ForeignAddressList *foreign_address_iterator;
6053 struct TransportPlugin *transport_plugin;
6054 struct ReadyList *ready_iterator;
6055 char *addr_buf;
6056
6057 ready_iterator = neighbor_iterator->plugins;
6058 while (ready_iterator != NULL)
6059 {
6060 foreign_address_iterator = ready_iterator->addresses;
6061 while (foreign_address_iterator != NULL)
6062 {
6063 transport_plugin = foreign_address_iterator->ready_list->plugin;
6064 if (foreign_address_iterator->addr != NULL)
6065 {
6066 GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
6067 GNUNET_i2s(&neighbor_iterator->id),
6068 a2s (transport_plugin->short_name,
6069 foreign_address_iterator->addr,
6070 foreign_address_iterator->addrlen),
6071 (foreign_address_iterator->connected
6072 == GNUNET_YES) ? "CONNECTED"
6073 : "DISCONNECTED",
6074 (foreign_address_iterator->validated
6075 == GNUNET_YES) ? "VALIDATED"
6076 : "UNVALIDATED");
6077 transmit_address_to_client (tc, addr_buf);
6078 GNUNET_free (addr_buf);
6079 }
6080 else if (foreign_address_iterator->addrlen == 0)
6081 {
6082 GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
6083 GNUNET_i2s (&neighbor_iterator->id),
6084 "<inbound>",
6085 (foreign_address_iterator->connected
6086 == GNUNET_YES) ? "CONNECTED"
6087 : "DISCONNECTED",
6088 (foreign_address_iterator->validated
6089 == GNUNET_YES) ? "VALIDATED"
6090 : "UNVALIDATED");
6091 transmit_address_to_client (tc, addr_buf);
6092 GNUNET_free (addr_buf);
6093 }
6094
6095 foreign_address_iterator = foreign_address_iterator->next;
6096 }
6097 ready_iterator = ready_iterator->next;
6098 }
6099 return GNUNET_OK;
6100}
6101
6102
6023/** 6103/**
6024 * Handle AddressIterateMessage 6104 * Handle AddressIterateMessage
6025 * 6105 *
@@ -6032,14 +6112,8 @@ handle_address_iterate (void *cls,
6032 struct GNUNET_SERVER_Client *client, 6112 struct GNUNET_SERVER_Client *client,
6033 const struct GNUNET_MessageHeader *message) 6113 const struct GNUNET_MessageHeader *message)
6034{ 6114{
6035 struct NeighbourList *neighbor_iterator;
6036 struct ReadyList *ready_iterator;
6037 struct ForeignAddressList *foreign_address_iterator;
6038 struct TransportPlugin *transport_plugin;
6039
6040 uint16_t size;
6041 struct GNUNET_SERVER_TransmitContext *tc; 6115 struct GNUNET_SERVER_TransmitContext *tc;
6042 char *addr_buf; 6116 uint16_t size;
6043 6117
6044 size = ntohs (message->size); 6118 size = ntohs (message->size);
6045 if (size < sizeof (struct AddressIterateMessage)) 6119 if (size < sizeof (struct AddressIterateMessage))
@@ -6050,55 +6124,9 @@ handle_address_iterate (void *cls,
6050 } 6124 }
6051 GNUNET_SERVER_disable_receive_done_warning (client); 6125 GNUNET_SERVER_disable_receive_done_warning (client);
6052 tc = GNUNET_SERVER_transmit_context_create (client); 6126 tc = GNUNET_SERVER_transmit_context_create (client);
6053 6127 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
6054 neighbor_iterator = neighbours; 6128 &output_addresses,
6055 while (neighbor_iterator != NULL) 6129 tc);
6056 {
6057 ready_iterator = neighbor_iterator->plugins;
6058 while (ready_iterator != NULL)
6059 {
6060 foreign_address_iterator = ready_iterator->addresses;
6061 while (foreign_address_iterator != NULL)
6062 {
6063 transport_plugin = foreign_address_iterator->ready_list->plugin;
6064 if (foreign_address_iterator->addr != NULL)
6065 {
6066 GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
6067 GNUNET_i2s(&neighbor_iterator->id),
6068 a2s (transport_plugin->short_name,
6069 foreign_address_iterator->addr,
6070 foreign_address_iterator->addrlen),
6071 (foreign_address_iterator->connected
6072 == GNUNET_YES) ? "CONNECTED"
6073 : "DISCONNECTED",
6074 (foreign_address_iterator->validated
6075 == GNUNET_YES) ? "VALIDATED"
6076 : "UNVALIDATED");
6077 transmit_address_to_client (tc, addr_buf);
6078 GNUNET_free (addr_buf);
6079 }
6080 else if (foreign_address_iterator->addrlen == 0)
6081 {
6082 GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
6083 GNUNET_i2s (&neighbor_iterator->id),
6084 "<inbound>",
6085 (foreign_address_iterator->connected
6086 == GNUNET_YES) ? "CONNECTED"
6087 : "DISCONNECTED",
6088 (foreign_address_iterator->validated
6089 == GNUNET_YES) ? "VALIDATED"
6090 : "UNVALIDATED");
6091 transmit_address_to_client (tc, addr_buf);
6092 GNUNET_free (addr_buf);
6093 }
6094
6095 foreign_address_iterator = foreign_address_iterator->next;
6096 }
6097 ready_iterator = ready_iterator->next;
6098 }
6099 neighbor_iterator = neighbor_iterator->next;
6100 }
6101
6102 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 6130 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
6103 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY); 6131 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
6104 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 6132 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
@@ -6155,6 +6183,24 @@ start_transport (struct GNUNET_SERVER_Handle *server,
6155} 6183}
6156 6184
6157 6185
6186static int
6187null_mq_client_pointers (void *cls,
6188 const GNUNET_HashCode *key,
6189 void *value)
6190{
6191 struct TransportClient *pos = cls;
6192 struct NeighbourList *n = value;
6193 struct MessageQueue *mq;
6194
6195 for (mq = n->messages_head; mq != NULL; mq = mq->next)
6196 {
6197 if (mq->client == pos)
6198 mq->client = NULL; /* do not use anymore! */
6199 }
6200 return GNUNET_OK;
6201}
6202
6203
6158/** 6204/**
6159 * Called whenever a client is disconnected. Frees our 6205 * Called whenever a client is disconnected. Frees our
6160 * resources associated with that client. 6206 * resources associated with that client.
@@ -6171,8 +6217,6 @@ client_disconnect_notification (void *cls,
6171 struct ClientMessageQueueEntry *mqe; 6217 struct ClientMessageQueueEntry *mqe;
6172 struct Blacklisters *bl; 6218 struct Blacklisters *bl;
6173 struct BlacklistCheck *bc; 6219 struct BlacklistCheck *bc;
6174 struct NeighbourList *n;
6175 struct MessageQueue *mq;
6176 6220
6177 if (client == NULL) 6221 if (client == NULL)
6178 return; 6222 return;
@@ -6231,14 +6275,9 @@ client_disconnect_notification (void *cls,
6231 pos->message_count--; 6275 pos->message_count--;
6232 GNUNET_free (mqe); 6276 GNUNET_free (mqe);
6233 } 6277 }
6234 for (n = neighbours; n != NULL; n = n->next) 6278 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
6235 { 6279 &null_mq_client_pointers,
6236 for (mq = n->messages_head; mq != NULL; mq = mq->next) 6280 pos);
6237 {
6238 if (mq->client == pos)
6239 mq->client = NULL; /* do not use anymore! */
6240 }
6241 }
6242 if (prev == NULL) 6281 if (prev == NULL)
6243 clients = pos->next; 6282 clients = pos->next;
6244 else 6283 else
@@ -6258,6 +6297,24 @@ client_disconnect_notification (void *cls,
6258} 6297}
6259 6298
6260 6299
6300static int
6301disconnect_all_neighbours (void *cls,
6302 const GNUNET_HashCode *key,
6303 void *value)
6304{
6305 struct NeighbourList *n = value;
6306
6307#if DEBUG_TRANSPORT
6308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6309 "Disconnecting peer `%4s', %s\n",
6310 GNUNET_i2s(&n->id),
6311 "SHUTDOWN_TASK");
6312#endif
6313 disconnect_neighbour (n, GNUNET_NO);
6314 return GNUNET_OK;
6315}
6316
6317
6261/** 6318/**
6262 * Function called when the service shuts down. Unloads our plugins 6319 * Function called when the service shuts down. Unloads our plugins
6263 * and cancels pending validations. 6320 * and cancels pending validations.
@@ -6273,15 +6330,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
6273 struct CheckHelloValidatedContext *chvc; 6330 struct CheckHelloValidatedContext *chvc;
6274 6331
6275 shutdown_in_progress = GNUNET_YES; 6332 shutdown_in_progress = GNUNET_YES;
6276 while (neighbours != NULL) 6333 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
6277 { 6334 &disconnect_all_neighbours,
6278#if DEBUG_TRANSPORT 6335 NULL);
6279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6280 "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&neighbours->id),
6281 "SHUTDOWN_TASK");
6282#endif
6283 disconnect_neighbour (neighbours, GNUNET_NO);
6284 }
6285#if DEBUG_TRANSPORT 6336#if DEBUG_TRANSPORT
6286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 6337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6287 "Transport service is unloading plugins...\n"); 6338 "Transport service is unloading plugins...\n");
@@ -6364,6 +6415,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
6364 explicitly!? */ 6415 explicitly!? */
6365 GNUNET_break (bl_head == NULL); 6416 GNUNET_break (bl_head == NULL);
6366 GNUNET_break (bc_head == NULL); 6417 GNUNET_break (bc_head == NULL);
6418 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
6419 neighbours = NULL;
6367} 6420}
6368 6421
6369 6422
@@ -6375,104 +6428,130 @@ void ats_result_cb ()
6375 6428
6376 6429
6377#if HAVE_LIBGLPK 6430#if HAVE_LIBGLPK
6431struct AtsBuildContext
6432{
6433 struct ATS_mechanism * mechanisms;
6434 struct ATS_peer *peers;
6435 int c_peers;
6436 int c_mechs;
6437};
6438
6439
6440static int
6441find_and_count_addresses (void *cls,
6442 const GNUNET_HashCode *key,
6443 void *value)
6444{
6445 struct AtsBuildContext *abc = cls;
6446 struct NeighbourList *next = value;
6447 int found_addresses = GNUNET_NO;
6448
6449 struct ReadyList *r_next = next->plugins;
6450 while (r_next != NULL)
6451 {
6452 struct ForeignAddressList * a_next = r_next->addresses;
6453 while (a_next != NULL)
6454 {
6455 abc->c_mechs++;
6456 found_addresses = GNUNET_YES;
6457 a_next = a_next->next;
6458 }
6459 r_next = r_next->next;
6460 }
6461 if (found_addresses)
6462 abc->c_peers++;
6463 return GNUNET_OK;
6464}
6465
6466
6467static int
6468setup_ats_problem (void *cls,
6469 const GNUNET_HashCode *key,
6470 void *value)
6471{
6472 struct AtsBuildContext *abc = cls;
6473 struct NeighbourList *next = value;
6474
6475 int found_addresses = GNUNET_NO;
6476 struct ReadyList *r_next = next->plugins;
6477 while (r_next != NULL)
6478 {
6479 struct ForeignAddressList * a_next = r_next->addresses;
6480 while (a_next != NULL)
6481 {
6482 if (found_addresses == GNUNET_NO)
6483 {
6484 abc->peers[abc->c_peers].peer = next->id;
6485 abc->peers[abc->c_peers].m_head = NULL;
6486 abc->peers[abc->c_peers].m_tail = NULL;
6487 abc->peers[abc->c_peers].f = 1.0 / abc->c_mechs;
6488 }
6489 abc->mechanisms[abc->c_mechs].addr = a_next;
6490 abc->mechanisms[abc->c_mechs].col_index = abc->c_mechs;
6491 abc->mechanisms[abc->c_mechs].peer = &abc->peers[abc->c_peers];
6492 abc->mechanisms[abc->c_mechs].next = NULL;
6493 abc->mechanisms[abc->c_mechs].plugin = r_next->plugin;
6494 abc->mechanisms[abc->c_mechs].ressources = a_next->ressources;
6495 abc->mechanisms[abc->c_mechs].quality = a_next->quality;
6496 GNUNET_CONTAINER_DLL_insert_tail(abc->peers[abc->c_peers].m_head,
6497 abc->peers[abc->c_peers].m_tail,
6498 &abc->mechanisms[abc->c_mechs]);
6499 found_addresses = GNUNET_YES;
6500 abc->c_mechs++;
6501 a_next = a_next->next;
6502 }
6503 r_next = r_next->next;
6504 }
6505 if (found_addresses == GNUNET_YES)
6506 abc->c_peers++;
6507 return GNUNET_OK;
6508}
6509
6510
6378static void 6511static void
6379create_ats_information ( struct ATS_peer **p, 6512create_ats_information ( struct ATS_peer **p,
6380 int * c_p, 6513 int * c_p,
6381 struct ATS_mechanism ** m, 6514 struct ATS_mechanism ** m,
6382 int * c_m ) 6515 int * c_m )
6383{ 6516{
6517 struct AtsBuildContext abc;
6518
6384#if VERBOSE_ATS 6519#if VERBOSE_ATS
6385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 6520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6386 "ATS requires clean address information\n"); 6521 "ATS requires clean address information\n");
6387#endif 6522#endif
6388 struct ATS_mechanism * mechanisms; 6523 abc.c_peers = 0;
6389 struct ATS_peer *peers; 6524 abc.c_mechs = 0;
6390 int c_peers = 0; 6525 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
6391 int c_mechs = 0; 6526 &find_and_count_addresses,
6392 struct NeighbourList *next = neighbours; 6527 &abc);
6393
6394 while (next!=NULL)
6395 {
6396 int found_addresses = GNUNET_NO;
6397 struct ReadyList *r_next = next->plugins;
6398 while (r_next != NULL)
6399 {
6400 struct ForeignAddressList * a_next = r_next->addresses;
6401 while (a_next != NULL)
6402 {
6403 c_mechs++;
6404 found_addresses = GNUNET_YES;
6405 a_next = a_next->next;
6406 }
6407 r_next = r_next->next;
6408 }
6409 if (found_addresses) c_peers++;
6410 next = next->next;
6411 }
6412
6413#if VERBOSE_ATS 6528#if VERBOSE_ATS
6414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 6529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6415 "Found %u peers with % u transport mechanisms\n", c_peers, c_mechs); 6530 "Found %u peers with % u transport mechanisms\n", c_peers, c_mechs);
6416#endif 6531#endif
6417 6532
6418 if ((c_peers == 0) && (c_mechs == 0)) 6533 if ( (abc.c_peers == 0) && (abc.c_mechs == 0) )
6419 {
6420 peers = NULL;
6421 (*c_p) = 0;
6422 mechanisms = NULL;
6423 (*c_m) = 0;
6424 return;
6425 }
6426
6427 mechanisms = GNUNET_malloc((1+c_mechs) * sizeof (struct ATS_mechanism));
6428 peers = GNUNET_malloc((1+c_peers) * sizeof (struct ATS_peer));
6429
6430 c_mechs = 1;
6431 c_peers = 1;
6432
6433 next = neighbours;
6434 while (next!=NULL)
6435 { 6534 {
6436 int found_addresses = GNUNET_NO; 6535 *p = NULL;
6437 struct ReadyList *r_next = next->plugins; 6536 (*c_p) = 0;
6438 while (r_next != NULL) 6537 *m = NULL;
6439 { 6538 (*c_m) = 0;
6440 struct ForeignAddressList * a_next = r_next->addresses; 6539 return;
6441 while (a_next != NULL) 6540 }
6442 { 6541
6443 if (found_addresses == GNUNET_NO) 6542 abc.mechanisms = GNUNET_malloc((1+abc.c_mechs) * sizeof (struct ATS_mechanism));
6444 { 6543 abc.peers = GNUNET_malloc((1+abc.c_peers) * sizeof (struct ATS_peer));
6445 peers[c_peers].peer = next->id; 6544 abc.c_mechs = 1;
6446 peers[c_peers].m_head = NULL; 6545 abc.c_peers = 1;
6447 peers[c_peers].m_tail = NULL; 6546 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
6448 peers[c_peers].f = 1.0 / c_mechs; 6547 &setup_ats_problem,
6449 } 6548 &abc);
6450 mechanisms[c_mechs].addr = a_next; 6549 abc.c_mechs--;
6451 mechanisms[c_mechs].col_index = c_mechs; 6550 abc.c_peers--;
6452 mechanisms[c_mechs].peer = &peers[c_peers]; 6551 (*c_m) = abc.c_mechs;
6453 mechanisms[c_mechs].next = NULL; 6552 (*c_p) = abc.c_peers;
6454 mechanisms[c_mechs].plugin = r_next->plugin; 6553 (*p) = abc.peers;
6455 mechanisms[c_mechs].ressources = a_next->ressources; 6554 (*m) = abc.mechanisms;
6456 mechanisms[c_mechs].quality = a_next->quality;
6457 GNUNET_CONTAINER_DLL_insert_tail(peers[c_peers].m_head,
6458 peers[c_peers].m_tail,
6459 &mechanisms[c_mechs]);
6460 found_addresses = GNUNET_YES;
6461 c_mechs++;
6462 a_next = a_next->next;
6463 }
6464 r_next = r_next->next;
6465 }
6466 if (found_addresses == GNUNET_YES)
6467 c_peers++;
6468 next = next->next;
6469 }
6470 c_mechs--;
6471 c_peers--;
6472 (*c_m) = c_mechs;
6473 (*c_p) = c_peers;
6474 (*p) = peers;
6475 (*m) = mechanisms;
6476} 6555}
6477 6556
6478 6557
@@ -6571,6 +6650,7 @@ run (void *cls,
6571 cfg = c; 6650 cfg = c;
6572 stats = GNUNET_STATISTICS_create ("transport", cfg); 6651 stats = GNUNET_STATISTICS_create ("transport", cfg);
6573 validation_map = GNUNET_CONTAINER_multihashmap_create (64); 6652 validation_map = GNUNET_CONTAINER_multihashmap_create (64);
6653 neighbours = GNUNET_CONTAINER_multihashmap_create (256);
6574 /* parse configuration */ 6654 /* parse configuration */
6575 if ((GNUNET_OK != 6655 if ((GNUNET_OK !=
6576 GNUNET_CONFIGURATION_get_value_number (c, 6656 GNUNET_CONFIGURATION_get_value_number (c,
@@ -6593,6 +6673,8 @@ run (void *cls,
6593 } 6673 }
6594 GNUNET_CONTAINER_multihashmap_destroy (validation_map); 6674 GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6595 validation_map = NULL; 6675 validation_map = NULL;
6676 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
6677 neighbours = NULL;
6596 return; 6678 return;
6597 } 6679 }
6598 6680
@@ -6610,6 +6692,8 @@ run (void *cls,
6610 } 6692 }
6611 GNUNET_CONTAINER_multihashmap_destroy (validation_map); 6693 GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6612 validation_map = NULL; 6694 validation_map = NULL;
6695 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
6696 neighbours = NULL;
6613 GNUNET_free (keyfile); 6697 GNUNET_free (keyfile);
6614 return; 6698 return;
6615 } 6699 }
@@ -6628,6 +6712,8 @@ run (void *cls,
6628 } 6712 }
6629 GNUNET_CONTAINER_multihashmap_destroy (validation_map); 6713 GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6630 validation_map = NULL; 6714 validation_map = NULL;
6715 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
6716 neighbours = NULL;
6631 return; 6717 return;
6632 } 6718 }
6633 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); 6719 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);