#include "gnunet_service_lib.h"
#include "gnunet_signatures.h"
#include "gnunet_transport_plugin.h"
+#include "gnunet-service-transport_ats.h"
#include "transport.h"
-#include "transport_ats.h"
+
#define DEBUG_BLACKLIST GNUNET_NO
#define DEBUG_TRANSPORT_HELLO GNUNET_NO
+#define DEBUG_INBOUND GNUNET_NO
+
/**
* Should we do some additional checks (to validate behavior
* of clients)?
struct GNUNET_CONTAINER_MultiHashMap *blacklist;
};
-struct NeighbourList;
+struct NeighbourMapEntry;
/**
* For each neighbour we keep a list of messages
/**
* To which neighbour does this ready list belong to?
*/
- struct NeighbourList *neighbour;
+ struct NeighbourMapEntry *neighbour;
};
/**
- * Entry in linked list of all of our current neighbours.
+ * Entry in neighbours.
*/
-struct NeighbourList
+struct NeighbourMapEntry
{
- /**
- * This is a linked list.
- */
- struct NeighbourList *next;
-
/**
* Which of our transports is connected to this peer
* and what is their status?
*/
int public_key_valid;
+ /**
+ * Are we already in the process of disconnecting this neighbour?
+ */
+ int in_disconnect;
+
/**
* Performance data for the peer.
*/
};
+/**
+ * All zero hash for comparison.
+ */
+static GNUNET_HashCode null_hash;
+
/**
* Our HELLO message.
*/
/**
* All known neighbours and their HELLOs.
*/
-static struct NeighbourList *neighbours;
+static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
/**
* Number of neighbours we'd like to have.
* disconnected or must we ask all plugins to
* disconnect?
*/
-static void disconnect_neighbour (struct NeighbourList *n, int check);
+static void disconnect_neighbour (struct NeighbourMapEntry *n, int check);
/**
* Check the ready list for the given neighbour and if a plugin is
*
* @param nexi target peer for which to transmit
*/
-static void try_transmission_to_peer (struct NeighbourList *n);
+static void try_transmission_to_peer (struct NeighbourMapEntry *n);
struct ForeignAddressList * get_preferred_ats_address (
- struct NeighbourList *n);
+ struct NeighbourMapEntry *n);
/**
* Find an entry in the neighbour list for a particular peer.
*
* @return NULL if not found.
*/
-static struct NeighbourList *
+static struct NeighbourMapEntry *
find_neighbour (const struct GNUNET_PeerIdentity *key)
{
- struct NeighbourList *head = neighbours;
-
- while ((head != NULL) &&
- (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
- head = head->next;
- return head;
+ return GNUNET_CONTAINER_multihashmap_get (neighbours, &key->hashPubKey);
}
static int update_addr_value (struct ForeignAddressList *fal, uint32_t value , int ats_index)
fal->quality[c].values[1] = fal->quality[c].values[2];
fal->quality[c].values[2] = value;
set = GNUNET_YES;
+#if HAVE_LIBGLPK
ats_modify_problem_state (ats, ATS_QUALITY_UPDATED);
+#endif
}
}
if (set == GNUNET_NO)
{
fal->ressources[c].c = value;
set = GNUNET_YES;
+#if HAVE_LIBGLPK
ats_modify_problem_state (ats, ATS_COST_UPDATED);
+#endif
}
}
}
p = find_transport (plugin);
if ((p == NULL) || (addr_len == 0) || (addr == NULL))
return NULL;
-
return p->api->address_to_string (NULL,
addr,
addr_len);
- return NULL;
}
struct ClientMessageQueueEntry *q;
uint16_t msize;
+ /* Client==NULL when GNUNET_SERVER_Client disconnected and was
+ * freed in client_disconnect_notification
+ */
+ if (client->client == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
memcpy (&q[1], msg, msize);
- GNUNET_CONTAINER_DLL_insert_after (client->message_queue_head,
- client->message_queue_tail,
- client->message_queue_tail,
- q);
+ GNUNET_CONTAINER_DLL_insert_tail (client->message_queue_head,
+ client->message_queue_tail,
+ q);
client->message_count++;
if (client->th == NULL)
{
*/
static void
transmit_send_ok (struct TransportClient *client,
- struct NeighbourList *n,
+ struct NeighbourMapEntry *n,
const struct GNUNET_PeerIdentity *target,
int result)
{
retry_transmission_task (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct NeighbourList *n = cls;
+ struct NeighbourMapEntry *n = cls;
n->retry_task = GNUNET_SCHEDULER_NO_TASK;
try_transmission_to_peer (n);
int result)
{
struct MessageQueue *mq = cls;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
GNUNET_STATISTICS_update (stats,
gettext_noop ("# bytes pending with plugins"),
}
else
{
- if (mq->specific_address->connected != GNUNET_NO)
+ if (mq->specific_address->connected == GNUNET_YES)
{
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
n = find_neighbour (&mq->neighbour_id);
if (mq->client != NULL)
transmit_send_ok (mq->client, n, target, result);
- if (n != NULL)
- {
- GNUNET_CONTAINER_DLL_remove (n->cont_head,
- n->cont_tail,
- mq);
- }
+ GNUNET_assert (n != NULL);
+ GNUNET_CONTAINER_DLL_remove (n->cont_head,
+ n->cont_tail,
+ mq);
GNUNET_free (mq);
- if (n != NULL)
- {
- if (result == GNUNET_OK)
- try_transmission_to_peer (n);
- else if (GNUNET_SCHEDULER_NO_TASK == n->retry_task)
- n->retry_task = GNUNET_SCHEDULER_add_now (&retry_transmission_task,
- n);
- }
+ if (result == GNUNET_OK)
+ try_transmission_to_peer (n);
+ else if (GNUNET_SCHEDULER_NO_TASK == n->retry_task)
+ n->retry_task = GNUNET_SCHEDULER_add_now (&retry_transmission_task,
+ n);
}
* @param neighbour target peer for which to transmit
*/
static void
-try_transmission_to_peer (struct NeighbourList *n)
+try_transmission_to_peer (struct NeighbourMapEntry *n)
{
struct ReadyList *rl;
struct MessageQueue *mq;
struct GNUNET_TIME_Relative timeout,
const char *message_buf,
size_t message_buf_size,
- int is_internal, struct NeighbourList *neighbour)
+ int is_internal, struct NeighbourMapEntry *neighbour)
{
struct MessageQueue *mq;
* @param n neighbour to PING
*/
static void
-transmit_plain_ping (struct NeighbourList *n)
+transmit_plain_ping (struct NeighbourMapEntry *n)
{
struct ValidationEntry *ve;
struct TransportPingMessage ping;
* @param fal address to set to 'connected'
*/
static void
-mark_address_connected (struct ForeignAddressList *fal)
+mark_address_connected(struct ForeignAddressList *fal)
{
struct ForeignAddressList *pos;
- int cnt;
+ struct ForeignAddressList *inbound;
+ struct ForeignAddressList *outbound;
GNUNET_assert (GNUNET_YES == fal->validated);
if (fal->connected == GNUNET_YES)
return; /* nothing to do */
- cnt = GNUNET_YES;
+ inbound = NULL;
+ outbound = NULL;
+
pos = fal->ready_list->addresses;
+ while (pos != NULL)
+ {
+ /* Already have inbound address, and this is also an inbound address, don't switch!! */
+ if ( (GNUNET_YES == pos->connected) &&
+ (0 == pos->addrlen) &&
+ (0 == fal->addrlen) )
+ return;
+ if ( (0 == pos->addrlen) &&
+ (GNUNET_YES == pos->connected) )
+ inbound = pos;
+ pos = pos->next;
+ }
+ pos = fal->ready_list->addresses;
while (pos != NULL)
{
- if (GNUNET_YES == pos->connected)
- {
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Marking address `%s' as no longer connected (due to connect on other address)\n",
- a2s (pos->ready_list->plugin->short_name,
- pos->addr,
- pos->addrlen));
-#endif
- GNUNET_break (cnt == GNUNET_YES);
- cnt = GNUNET_NO;
- pos->connected = GNUNET_NO;
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# connected addresses"),
- -1,
- GNUNET_NO);
- }
+ /* Already have outbound address, and this is also an outbound address, don't switch!! */
+ if ( (GNUNET_YES == pos->connected) &&
+ (0 < pos->addrlen) &&
+ (0 < fal->addrlen) )
+ return;
+ if ( (0 < pos->addrlen) && (GNUNET_YES == pos->connected) )
+ outbound = pos;
pos = pos->next;
}
- fal->connected = GNUNET_YES;
- if (GNUNET_YES == cnt)
+#if DEBUG_INBOUND
+ if (inbound != NULL)
+ fprintf(stderr, "Peer: %s, have inbound connection.\n", GNUNET_i2s(&my_identity));
+ if (outbound != NULL)
+ fprintf(stderr, "Peer: %s, have outbound connection.\n", GNUNET_i2s(&my_identity));
+#endif
+
+ /* Have an inbound connection to this peer which is valid; our id is lower, ignore outbound connection! */
+ if ((inbound != NULL) && (0 != fal->addrlen) && (1
+ == GNUNET_CRYPTO_hash_xorcmp (&inbound->ready_list->neighbour->id.hashPubKey,
+ &my_identity.hashPubKey, &null_hash)))
{
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# connected addresses"),
- 1,
- GNUNET_NO);
+#if DEBUG_INBOUND
+ fprintf(stderr, "Peer: %s, had inbound connection, ignoring outbound!\n", GNUNET_i2s(&my_identity));
+#endif
+ return;
+ }
+ else if ((outbound != NULL) && (0 == fal->addrlen) && ((-1
+ == GNUNET_CRYPTO_hash_xorcmp (&outbound->ready_list->neighbour->id.hashPubKey,
+ &my_identity.hashPubKey, &null_hash))))
+ {
+#if DEBUG_INBOUND
+ fprintf(stderr, "Peer: %s, have outbound connection, ignoring inbound!\n", GNUNET_i2s(&my_identity));
+#endif
+ return;
+ }
+
+ pos = fal->ready_list->addresses;
+ while (pos != NULL)
+ {
+ if ((GNUNET_YES == pos->connected) && (0 < pos->addrlen))
+ {
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Marking address `%s' as no longer connected (due to connect on other address)\n",
+ a2s (pos->ready_list->plugin->short_name, pos->addr,
+ pos->addrlen));
+#endif
+#if DEBUG_INBOUND
+ fprintf(stderr,
+ "Peer: %s, setting %s connection to disconnected.\n",
+ GNUNET_i2s(&my_identity),
+ (0 == pos->addrlen) ? "INBOUND" : "OUTBOUND");
+#endif
+ pos->connected = GNUNET_NO;
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connected addresses"), -1,
+ GNUNET_NO);
+ }
+ pos = pos->next;
}
+ GNUNET_assert (GNUNET_NO == fal->connected);
+ fal->connected = GNUNET_YES;
+ GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"),
+ 1, GNUNET_NO);
}
* @return selected address, NULL if we have none
*/
struct ForeignAddressList *
-find_ready_address(struct NeighbourList *neighbour)
+find_ready_address(struct NeighbourMapEntry *neighbour)
{
struct ReadyList *head = neighbour->plugins;
struct ForeignAddressList *addresses;
}
+
+static int
+transmit_our_hello_if_pong (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct NeighbourMapEntry *npos = value;
+
+ if (GNUNET_YES != npos->received_pong)
+ return GNUNET_OK;
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+ "Transmitting updated `%s' to neighbour `%4s'\n",
+ "HELLO", GNUNET_i2s (&npos->id));
+#endif
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# transmitted my HELLO to other peers"),
+ 1,
+ GNUNET_NO);
+ transmit_to_peer (NULL, NULL, 0,
+ HELLO_ADDRESS_EXPIRATION,
+ (const char *) our_hello,
+ GNUNET_HELLO_size(our_hello),
+ GNUNET_NO, npos);
+ return GNUNET_OK;
+}
+
+
/**
* Construct our HELLO message from all of the addresses of
* all of the transports.
{
struct GNUNET_HELLO_Message *hello;
struct TransportClient *cpos;
- struct NeighbourList *npos;
struct GeneratorContext gc;
hello_task = GNUNET_SCHEDULER_NO_TASK;
GNUNET_free_non_null (our_hello);
our_hello = hello;
GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
- for (npos = neighbours; npos != NULL; npos = npos->next)
- {
- if (! npos->received_pong)
- continue;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Transmitting updated `%s' to neighbour `%4s'\n",
- "HELLO", GNUNET_i2s (&npos->id));
-#endif
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# transmitted my HELLO to other peers"),
- 1,
- GNUNET_NO);
- transmit_to_peer (NULL, NULL, 0,
- HELLO_ADDRESS_EXPIRATION,
- (const char *) our_hello,
- GNUNET_HELLO_size(our_hello),
- GNUNET_NO, npos);
- }
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &transmit_our_hello_if_pong,
+ NULL);
}
*/
static void
try_fast_reconnect (struct TransportPlugin *p,
- struct NeighbourList *nl)
+ struct NeighbourMapEntry *nl)
{
/* FIXME-MW: fast reconnect / transport switching not implemented... */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
struct Session *session)
{
struct TransportPlugin *p = cls;
- struct NeighbourList *nl;
+ struct NeighbourMapEntry *nl;
struct ReadyList *rl;
struct ForeignAddressList *pos;
struct ForeignAddressList *prev;
return; /* was never marked as connected */
}
pos->session = NULL;
- pos->connected = GNUNET_NO;
+ if (GNUNET_YES == pos->connected)
+ {
+ pos->connected = GNUNET_NO;
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connected addresses"),
+ -1,
+ GNUNET_NO);
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
+ {
+ GNUNET_SCHEDULER_cancel (pos->revalidate_task);
+ pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
if (pos->addrlen != 0)
{
if (nl->received_pong != GNUNET_NO)
return;
}
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# connected addresses"),
- -1,
- GNUNET_NO);
-
/* was inbound connection, free 'pos' */
if (prev == NULL)
rl->addresses = pos->next;
GNUNET_SCHEDULER_cancel (pos->revalidate_task);
pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
}
- GNUNET_free_non_null(pos->ressources);
- GNUNET_free_non_null(pos->quality);
+ GNUNET_free_non_null (pos->ressources);
+ GNUNET_free_non_null (pos->quality);
+#if HAVE_LIBGLPK
ats_modify_problem_state (ats, ATS_MODIFIED);
-
+#endif
if (GNUNET_YES != pos->connected)
{
/* nothing else to do, connection was never up... */
GNUNET_free (pos);
return;
}
+ pos->connected = GNUNET_NO;
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connected addresses"),
+ -1,
+ GNUNET_NO);
GNUNET_free (pos);
if (nl->received_pong == GNUNET_NO)
ats_count = 2;
size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break(0);
- }
+ GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
cim = GNUNET_malloc (size);
cim->header.size = htons (size);
cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
cim->ats_count = htonl(2);
- (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
- (&(cim->ats))[0].value = htonl (distance);
- (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
- (&(cim->ats))[1].value = htonl ((uint32_t) latency.rel_value);
- (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- (&(cim->ats))[2].value = htonl (0);
+ (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+ (&cim->ats)[0].value = htonl (distance);
+ (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+ (&cim->ats)[1].value = htonl ((uint32_t) latency.rel_value);
+ (&cim->ats)[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+ (&cim->ats)[2].value = htonl (0);
memcpy (&cim->id, peer, sizeof (struct GNUNET_PeerIdentity));
- /* notify ats about connecting peer */
/* notify ats about connecting peer */
if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
- {
- ats_modify_problem_state(ats, ATS_MODIFIED);
- ats_calculate_bandwidth_distribution (ats, stats);
- }
-
-
+ {
+#if HAVE_LIBGLPK
+ ats_modify_problem_state(ats, ATS_MODIFIED);
+ ats_calculate_bandwidth_distribution (ats);
+#endif
+ }
cpos = clients;
while (cpos != NULL)
{
- transmit_to_client (cpos, &(cim->header), GNUNET_NO);
+ transmit_to_client (cpos, &cim->header, GNUNET_NO);
cpos = cpos->next;
}
-
GNUNET_free (cim);
}
/* notify ats about connecting peer */
if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
{
+#if HAVE_LIBGLPK
ats_modify_problem_state(ats, ATS_MODIFIED);
- ats_calculate_bandwidth_distribution (ats, stats);
+ ats_calculate_bandwidth_distribution (ats);
+#endif
}
cpos = clients;
* @return NULL if no such entry exists
*/
static struct ForeignAddressList *
-find_peer_address(struct NeighbourList *neighbour,
+find_peer_address(struct NeighbourMapEntry *neighbour,
const char *tname,
struct Session *session,
const char *addr,
* @return NULL if we do not have a transport plugin for 'tname'
*/
static struct ForeignAddressList *
-add_peer_address (struct NeighbourList *neighbour,
+add_peer_address (struct NeighbourMapEntry *neighbour,
const char *tname,
struct Session *session,
const char *addr,
neighbour_timeout_task (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct NeighbourList *n = cls;
+ struct NeighbourMapEntry *n = cls;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
* Add the given address to the list of foreign addresses
* available for the given peer (check for duplicates).
*
- * @param cls the respective 'struct NeighbourList' to update
+ * @param cls the respective 'struct NeighbourMapEntry' to update
* @param tname name of the transport
* @param expiration expiration time
* @param addr the address
const void *addr,
uint16_t addrlen)
{
- struct NeighbourList *n = cls;
+ struct NeighbourMapEntry *n = cls;
struct ForeignAddressList *fal;
int try;
* Add addresses in validated HELLO "h" to the set of addresses
* we have for this peer.
*
- * @param cls closure ('struct NeighbourList*')
+ * @param cls closure ('struct NeighbourMapEntry*')
* @param peer id of the peer, NULL for last call
* @param h hello message for the peer (can be NULL)
* @param err_msg NULL if successful, otherwise contains error message
const struct GNUNET_HELLO_Message *h,
const char *err_msg)
{
- struct NeighbourList *n = cls;
+ struct NeighbourMapEntry *n = cls;
if (err_msg != NULL)
{
* @param do_hello should we schedule transmitting a HELLO
* @return the new neighbour list entry
*/
-static struct NeighbourList *
+static struct NeighbourMapEntry *
setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
int do_hello)
{
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
struct TransportPlugin *tp;
struct ReadyList *rl;
gettext_noop ("# active neighbours"),
1,
GNUNET_NO);
- n = GNUNET_malloc (sizeof (struct NeighbourList));
- n->next = neighbours;
- neighbours = n;
+ n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
n->id = *peer;
n->peer_timeout =
GNUNET_TIME_relative_to_absolute
n->distance = -1;
n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
&neighbour_timeout_task, n);
+ GNUNET_CONTAINER_multihashmap_put (neighbours,
+ &n->id.hashPubKey,
+ n,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
if (do_hello)
{
GNUNET_STATISTICS_update (stats,
* @param n NULL if communication is not acceptable
*/
typedef void (*SetupContinuation)(void *cls,
- struct NeighbourList *n);
+ struct NeighbourMapEntry *n);
/**
/**
- * Obtain a 'struct NeighbourList' for the given peer. If such an entry
+ * Obtain a 'struct NeighbourMapEntry' for the given peer. If such an entry
* does not yet exist, check the blacklist. If the blacklist says creating
* one is acceptable, create one and call the continuation; otherwise
* call the continuation with NULL.
*
- * @param peer peer to setup or look up a struct NeighbourList for
+ * @param peer peer to setup or look up a struct NeighbourMapEntry for
* @param do_hello should we also schedule sending our HELLO to the peer
* if this is a new record
* @param cont function to call with the 'struct NeigbhbourList*'
SetupContinuation cont,
void *cont_cls)
{
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
struct BlacklistCheck *bc;
n = find_neighbour(peer);
* Function called with the result of querying a new blacklister about
* it being allowed (or not) to continue to talk to an existing neighbour.
*
- * @param cls the original 'struct NeighbourList'
+ * @param cls the original 'struct NeighbourMapEntry'
* @param n NULL if we need to disconnect
*/
static void
confirm_or_drop_neighbour (void *cls,
- struct NeighbourList *n)
+ struct NeighbourMapEntry *n)
{
- struct NeighbourList * orig = cls;
+ struct NeighbourMapEntry * orig = cls;
if (n == NULL)
{
}
+struct TestConnectionContext
+{
+ int first;
+
+ struct Blacklisters *bl;
+};
+
+
+static int
+test_connection_ok (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct TestConnectionContext *tcc = cls;
+ struct NeighbourMapEntry *n = value;
+ struct BlacklistCheck *bc;
+
+
+ bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+ GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
+ bc->peer = n->id;
+ bc->do_hello = GNUNET_NO;
+ bc->cont = &confirm_or_drop_neighbour;
+ bc->cont_cls = n;
+ bc->bl_pos = tcc->bl;
+ if (GNUNET_YES == tcc->first)
+ {
+ /* all would wait for the same client, no need to
+ create more than just the first task right now */
+ bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+ bc);
+ tcc->first = GNUNET_NO;
+ }
+ return GNUNET_OK;
+}
+
+
/**
* Handle a request to start a blacklist.
*
const struct GNUNET_MessageHeader *message)
{
struct Blacklisters *bl;
- struct BlacklistCheck *bc;
- struct NeighbourList *n;
+ struct TestConnectionContext tcc;
bl = bl_head;
while (bl != NULL)
GNUNET_SERVER_client_keep (client);
GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
/* confirm that all existing connections are OK! */
- n = neighbours;
- while (NULL != n)
- {
- bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
- GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
- bc->peer = n->id;
- bc->do_hello = GNUNET_NO;
- bc->cont = &confirm_or_drop_neighbour;
- bc->cont_cls = n;
- bc->bl_pos = bl;
- if (n == neighbours) /* all would wait for the same client, no need to
- create more than just the first task right now */
- bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
- bc);
- n = n->next;
- }
+ tcc.bl = bl;
+ tcc.first = GNUNET_YES;
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &test_connection_ok,
+ &tcc);
}
struct ForeignAddressList *peer_address = cls;
struct TransportPlugin *tp;
struct ValidationEntry *va;
- struct NeighbourList *neighbour;
+ struct NeighbourMapEntry *neighbour;
struct TransportPingMessage ping;
struct CheckAddressExistsClosure caec;
char * message_buf;
peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
+ GNUNET_assert (peer_address != NULL);
tp = peer_address->ready_list->plugin;
neighbour = peer_address->ready_list->neighbour;
if (GNUNET_YES != neighbour->public_key_valid)
caec.session = peer_address->session;
caec.exists = GNUNET_NO;
- /* Inbound address, we won't have in validation map! */
- if (0 == peer_address->addrlen)
- fprintf(stderr, "Sending periodic ping to inbound address!??\n");
-
GNUNET_CONTAINER_multihashmap_iterate (validation_map,
&check_address_exists,
&caec);
HELLO_VERIFICATION_TIMEOUT,
message_buf, tsize,
GNUNET_YES, neighbour);
- GNUNET_free(message_buf);
+ GNUNET_free (message_buf);
schedule_next_ping (peer_address);
}
GNUNET_TIME_UNIT_SECONDS);
/* randomize a bit (to avoid doing all at the same time) */
delay.rel_value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
+
+ GNUNET_assert (fal->revalidate_task == GNUNET_SCHEDULER_NO_TASK);
fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(delay,
&send_periodic_ping,
fal);
*/
static void
handle_payload_message (const struct GNUNET_MessageHeader *message,
- struct NeighbourList *n)
+ struct NeighbourMapEntry *n)
{
struct InboundMessage *im;
struct TransportClient *cpos;
unsigned int challenge = ntohl(pong->challenge);
struct GNUNET_HELLO_Message *hello;
struct GNUNET_PeerIdentity target;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
struct ForeignAddressList *fal;
struct OwnAddressList *oal;
struct TransportPlugin *tp;
*/
static void
transmit_hello_and_ping (void *cls,
- struct NeighbourList *neighbour)
+ struct NeighbourMapEntry *neighbour)
{
struct ValidationEntry *va = cls;
struct ForeignAddressList *peer_address;
HELLO_VERIFICATION_TIMEOUT,
message_buf, tsize,
GNUNET_YES, neighbour);
- GNUNET_free(message_buf);
+ GNUNET_free (message_buf);
}
struct GNUNET_HELLO_Message *plain_hello;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
struct GNUNET_PeerIdentity target;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
if (err_msg != NULL)
{
const struct GNUNET_HELLO_Message *hello;
struct CheckHelloValidatedContext *chvc;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
#if DEBUG_TRANSPORT_HELLO > 2
char *my_id;
#endif
}
#if BREAK_TESTS
- struct NeighbourList *temp_neighbor = find_neighbour(&target);
+ struct NeighbourMapEntry *temp_neighbor = find_neighbour(&target);
if ((NULL != temp_neighbor))
{
fprintf(stderr, "Already know peer, ignoring hello\n");
#if DEBUG_TRANSPORT_HELLO > 2
if (plugin != NULL)
{
- my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
#if DEBUG_TRANSPORT
+ my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%s: Starting validation of `%s' message for `%4s' via '%s' of size %u\n",
my_id,
GNUNET_i2s (&target),
plugin->short_name,
GNUNET_HELLO_size(hello));
+ GNUNET_free (my_id);
#endif
- GNUNET_free(my_id);
}
#endif
chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
* regardless of whether other addresses exist.
*/
static void
-disconnect_neighbour (struct NeighbourList *n, int check)
+disconnect_neighbour (struct NeighbourMapEntry *n, int check)
{
struct ReadyList *rpos;
- struct NeighbourList *npos;
- struct NeighbourList *nprev;
struct MessageQueue *mq;
struct ForeignAddressList *peer_addresses;
struct ForeignAddressList *peer_pos;
+ if (GNUNET_YES == n->in_disconnect)
+ return;
if (GNUNET_YES == check)
{
rpos = n->plugins;
peer_addresses = rpos->addresses;
while (peer_addresses != NULL)
{
- // Do not disconnect if: an address is connected or an inbound address exists
+ /* Do not disconnect if: an address is connected or an inbound address exists */
if ((GNUNET_YES == peer_addresses->connected) || (peer_addresses->addrlen == 0))
{
#if DEBUG_TRANSPORT
"Disconnecting from `%4s'\n",
GNUNET_i2s (&n->id));
#endif
-
- /* remove n from neighbours list */
- nprev = NULL;
- npos = neighbours;
- while ((npos != NULL) && (npos != n))
- {
- nprev = npos;
- npos = npos->next;
- }
- GNUNET_assert (npos != NULL);
- if (nprev == NULL)
- neighbours = n->next;
- else
- nprev->next = n->next;
+ n->in_disconnect = GNUNET_YES; /* prevent recursive entry */
/* notify all clients about disconnect */
if (GNUNET_YES == n->received_pong)
- notify_clients_disconnect (&n->id);
-
+ {
+ n->received_pong = GNUNET_NO;
+ notify_clients_disconnect (&n->id);
+ }
+#if HAVE_LIBGLPK
ats_modify_problem_state(ats, ATS_MODIFIED);
-
+#endif
/* clean up all plugins, cancel connections and pending transmissions */
while (NULL != (rpos = n->plugins))
{
peer_pos = rpos->addresses;
rpos->addresses = peer_pos->next;
if (peer_pos->connected == GNUNET_YES)
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# connected addresses"),
- -1,
- GNUNET_NO);
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connected addresses"),
+ -1,
+ GNUNET_NO);
+ peer_pos->connected = GNUNET_NO;
+ }
if (GNUNET_YES == peer_pos->validated)
GNUNET_STATISTICS_update (stats,
gettext_noop ("# peer addresses considered valid"),
GNUNET_SCHEDULER_cancel (peer_pos->revalidate_task);
peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
}
- GNUNET_free(peer_pos->ressources);
+ GNUNET_free (peer_pos->ressources);
peer_pos->ressources = NULL;
- GNUNET_free(peer_pos->quality);
+ GNUNET_free (peer_pos->quality);
peer_pos->ressources = NULL;
- GNUNET_free(peer_pos);
+ GNUNET_free (peer_pos);
}
GNUNET_free (rpos);
}
GNUNET_NO);
n->piter = NULL;
}
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (neighbours,
+ &n->id.hashPubKey,
+ n));
/* finally, free n itself */
GNUNET_STATISTICS_update (stats,
gettext_noop ("# active neighbours"),
struct SessionHeader *session_header = (struct SessionHeader*) session;
struct TransportPingMessage *ping;
struct TransportPongMessage *pong;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
struct ReadyList *rl;
struct ForeignAddressList *fal;
struct OwnAddressList *oal;
struct ReadyList *service_context;
struct ForeignAddressList *peer_address;
uint16_t msize;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
struct GNUNET_TIME_Relative ret;
uint32_t distance;
int c;
peer_address->distance = distance;
if (GNUNET_YES == peer_address->validated)
+ {
mark_address_connected (peer_address);
+ schedule_next_ping (peer_address);
+ }
+ else
+ {
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "New address is unvalidated, trying to validate it now\n");
+#endif
+ if (peer_address->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (peer_address->revalidate_task);
+ peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ peer_address->revalidate_task = GNUNET_SCHEDULER_add_now (&send_periodic_ping, peer_address);
+
+ }
peer_address->timeout
= GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
- schedule_next_ping (peer_address);
}
/* update traffic received amount ... */
msize = ntohs (message->size);
if ((ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ATS) &&
(ntohs(message->size) == (sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t))))
{
+#if HAVE_LIBGLPK
uint32_t value = ntohl(*((uint32_t *) &message[1]));
//GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GNUNET_MESSAGE_TYPE_TRANSPORT_ATS: %i \n", value);
/* Force ressource and quality update */
/* Force full rebuild */
if ((value == 1) && (ats != NULL))
ats_modify_problem_state(ats, ATS_MODIFIED);
+#endif
}
#if DEBUG_PING_PONG
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
- if (! n->received_pong)
+ if (GNUNET_YES != n->received_pong)
transmit_plain_ping (n);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
return ret;
}
+
+static int
+notify_client_about_neighbour (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct TransportClient *c = cls;
+ struct NeighbourMapEntry *n = value;
+ struct ConnectInfoMessage * cim;
+ uint32_t ats_count;
+ size_t size;
+
+ if (GNUNET_YES != n->received_pong)
+ return GNUNET_OK;
+
+ ats_count = 2;
+ size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+ GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
+ cim = GNUNET_malloc (size);
+ cim->header.size = htons (size);
+ cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+ cim->ats_count = htonl(ats_count);
+ (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+ (&(cim->ats))[2].value = htonl (0);
+ if (GNUNET_YES == n->received_pong)
+ {
+ (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+ (&cim->ats)[0].value = htonl (n->distance);
+ (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+ (&cim->ats)[1].value = htonl ((uint32_t) n->latency.rel_value);
+ cim->id = n->id;
+ transmit_to_client (c, &cim->header, GNUNET_NO);
+ }
+ GNUNET_free (cim);
+ return GNUNET_OK;
+}
+
+
/**
* Handle START-message. This is the first message sent to us
* by any client which causes us to add it to our list.
{
const struct StartMessage *start;
struct TransportClient *c;
- struct ConnectInfoMessage * cim;
- struct NeighbourList *n;
- uint32_t ats_count;
- size_t size;
start = (const struct StartMessage*) message;
#if DEBUG_TRANSPORT
(const struct GNUNET_MessageHeader *) our_hello,
GNUNET_NO);
/* tell new client about all existing connections */
- ats_count = 2;
- size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break(0);
- }
- cim = GNUNET_malloc (size);
- cim->header.size = htons (size);
- cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
- cim->ats_count = htonl(ats_count);
- (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- (&(cim->ats))[2].value = htonl (0);
- n = neighbours;
- while (n != NULL)
- {
- if (GNUNET_YES == n->received_pong)
- {
- (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
- (&(cim->ats))[0].value = htonl (n->distance);
- (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
- (&(cim->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
- cim->id = n->id;
- transmit_to_client (c, &cim->header, GNUNET_NO);
- }
- n = n->next;
- }
- GNUNET_free (cim);
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ ¬ify_client_about_neighbour,
+ c);
}
else
{
*/
static void
transmit_client_message (void *cls,
- struct NeighbourList *n)
+ struct NeighbourMapEntry *n)
{
struct TransmitClientMessageContext *tcmc = cls;
struct TransportClient *tc;
{
const struct QuotaSetMessage *qsm =
(const struct QuotaSetMessage *) message;
- struct NeighbourList *n;
+ struct NeighbourMapEntry *n;
GNUNET_STATISTICS_update (stats,
gettext_noop ("# SET QUOTA messages received"),
}
else
{
+ GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+ GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
}
}
const char *address;
uint16_t size;
struct GNUNET_SERVER_TransmitContext *tc;
- struct GNUNET_TIME_Absolute timeout;
struct GNUNET_TIME_Relative rtimeout;
int32_t numeric;
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- timeout = GNUNET_TIME_absolute_ntoh (alum->timeout);
- rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
+ rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
numeric = ntohl (alum->numeric_only);
lsPlugin = find_transport (nameTransport);
if (NULL == lsPlugin)
const struct GNUNET_MessageHeader *message)
{
const struct PeerAddressLookupMessage *peer_address_lookup;
- struct NeighbourList *neighbor_iterator;
+ struct NeighbourMapEntry *neighbor_iterator;
struct ReadyList *ready_iterator;
struct ForeignAddressList *foreign_address_iterator;
struct TransportPlugin *transport_plugin;
uint16_t size;
struct GNUNET_SERVER_TransmitContext *tc;
- struct GNUNET_TIME_Absolute timeout;
struct GNUNET_TIME_Relative rtimeout;
char *addr_buf;
}
peer_address_lookup = (const struct PeerAddressLookupMessage *) message;
- timeout = GNUNET_TIME_absolute_ntoh (peer_address_lookup->timeout);
- rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
+ rtimeout = GNUNET_TIME_relative_ntoh (peer_address_lookup->timeout);
- neighbor_iterator = neighbours;
- while (neighbor_iterator != NULL)
- {
- if (0 == memcmp(&neighbor_iterator->id, &peer_address_lookup->peer, sizeof(struct GNUNET_PeerIdentity)))
- break;
- neighbor_iterator = neighbor_iterator->next;
- }
+ neighbor_iterator = find_neighbour (&peer_address_lookup->peer);
/* Found no neighbor matching this peer id (shouldn't be possible, but...) */
if (neighbor_iterator == NULL)
transport_plugin = foreign_address_iterator->ready_list->plugin;
if (foreign_address_iterator->addr != NULL)
{
- GNUNET_asprintf (&addr_buf, "%s --- %s",
+ GNUNET_asprintf (&addr_buf, "%s --- %s, %s",
a2s (transport_plugin->short_name,
foreign_address_iterator->addr,
foreign_address_iterator->addrlen),
(foreign_address_iterator->connected
== GNUNET_YES) ? "CONNECTED"
- : "DISCONNECTED");
+ : "DISCONNECTED",
+ (foreign_address_iterator->validated
+ == GNUNET_YES) ? "VALIDATED"
+ : "UNVALIDATED");
transmit_address_to_client(tc, addr_buf);
- GNUNET_free(addr_buf);
+ GNUNET_free (addr_buf);
}
else if (foreign_address_iterator->addrlen == 0)
{
- GNUNET_asprintf (&addr_buf, "%s --- %s", "<inbound>",
+ GNUNET_asprintf (&addr_buf, "%s --- %s, %s", "<inbound>",
(foreign_address_iterator->connected
== GNUNET_YES) ? "CONNECTED"
- : "DISCONNECTED");
+ : "DISCONNECTED",
+ (foreign_address_iterator->validated
+ == GNUNET_YES) ? "VALIDATED"
+ : "UNVALIDATED");
transmit_address_to_client (tc, addr_buf);
- GNUNET_free(addr_buf);
+ GNUNET_free (addr_buf);
}
foreign_address_iterator = foreign_address_iterator->next;
GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
}
+
+
+static int
+output_addresses (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_SERVER_TransmitContext *tc = cls;
+ struct NeighbourMapEntry *neighbor_iterator = value;
+ struct ForeignAddressList *foreign_address_iterator;
+ struct TransportPlugin *transport_plugin;
+ struct ReadyList *ready_iterator;
+ char *addr_buf;
+
+ ready_iterator = neighbor_iterator->plugins;
+ while (ready_iterator != NULL)
+ {
+ foreign_address_iterator = ready_iterator->addresses;
+ while (foreign_address_iterator != NULL)
+ {
+ transport_plugin = foreign_address_iterator->ready_list->plugin;
+ if (foreign_address_iterator->addr != NULL)
+ {
+ GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
+ GNUNET_i2s(&neighbor_iterator->id),
+ a2s (transport_plugin->short_name,
+ foreign_address_iterator->addr,
+ foreign_address_iterator->addrlen),
+ (foreign_address_iterator->connected
+ == GNUNET_YES) ? "CONNECTED"
+ : "DISCONNECTED",
+ (foreign_address_iterator->validated
+ == GNUNET_YES) ? "VALIDATED"
+ : "UNVALIDATED");
+ transmit_address_to_client (tc, addr_buf);
+ GNUNET_free (addr_buf);
+ }
+ else if (foreign_address_iterator->addrlen == 0)
+ {
+ GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
+ GNUNET_i2s (&neighbor_iterator->id),
+ "<inbound>",
+ (foreign_address_iterator->connected
+ == GNUNET_YES) ? "CONNECTED"
+ : "DISCONNECTED",
+ (foreign_address_iterator->validated
+ == GNUNET_YES) ? "VALIDATED"
+ : "UNVALIDATED");
+ transmit_address_to_client (tc, addr_buf);
+ GNUNET_free (addr_buf);
+ }
+
+ foreign_address_iterator = foreign_address_iterator->next;
+ }
+ ready_iterator = ready_iterator->next;
+ }
+ return GNUNET_OK;
+}
+
+
/**
* Handle AddressIterateMessage
*
struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
- const struct AddressIterateMessage *address_iterate;
- struct NeighbourList *neighbor_iterator;
- struct ReadyList *ready_iterator;
- struct ForeignAddressList *foreign_address_iterator;
- struct TransportPlugin *transport_plugin;
-
- uint16_t size;
struct GNUNET_SERVER_TransmitContext *tc;
- struct GNUNET_TIME_Absolute timeout;
- struct GNUNET_TIME_Relative rtimeout;
- char *addr_buf;
+ uint16_t size;
size = ntohs (message->size);
if (size < sizeof (struct AddressIterateMessage))
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- address_iterate = (const struct AddressIterateMessage *) message;
-
- timeout = GNUNET_TIME_absolute_ntoh (address_iterate->timeout);
- rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
-
GNUNET_SERVER_disable_receive_done_warning (client);
tc = GNUNET_SERVER_transmit_context_create (client);
-
- neighbor_iterator = neighbours;
- while (neighbor_iterator != NULL)
- {
- ready_iterator = neighbor_iterator->plugins;
- while (ready_iterator != NULL)
- {
- foreign_address_iterator = ready_iterator->addresses;
- while (foreign_address_iterator != NULL)
- {
- transport_plugin = foreign_address_iterator->ready_list->plugin;
- if (foreign_address_iterator->addr != NULL)
- {
- GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
- GNUNET_i2s(&neighbor_iterator->id),
- a2s (transport_plugin->short_name,
- foreign_address_iterator->addr,
- foreign_address_iterator->addrlen),
- (foreign_address_iterator->connected
- == GNUNET_YES) ? "CONNECTED"
- : "DISCONNECTED",
- (foreign_address_iterator->validated
- == GNUNET_YES) ? "VALIDATED"
- : "UNVALIDATED");
- transmit_address_to_client (tc, addr_buf);
- GNUNET_free(addr_buf);
- }
- else if (foreign_address_iterator->addrlen == 0)
- {
- GNUNET_asprintf (&addr_buf, "%s:%s --- %s",
- GNUNET_i2s (&neighbor_iterator->id),
- "<inbound>",
- (foreign_address_iterator->connected
- == GNUNET_YES) ? "CONNECTED"
- : "DISCONNECTED",
- (foreign_address_iterator->validated
- == GNUNET_YES) ? "VALIDATED"
- : "UNVALIDATED");
- transmit_address_to_client (tc, addr_buf);
- GNUNET_free(addr_buf);
- }
-
- foreign_address_iterator = foreign_address_iterator->next;
- }
- ready_iterator = ready_iterator->next;
- }
- neighbor_iterator = neighbor_iterator->next;
- }
-
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &output_addresses,
+ tc);
GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
}
+static const struct GNUNET_MessageHeader *
+do_get_our_hello ()
+{
+ return (const struct GNUNET_MessageHeader*) our_hello;
+}
+
+
/**
* Setup the environment for this plugin.
*/
{
plug->env.cfg = cfg;
plug->env.my_identity = &my_identity;
- plug->env.our_hello = &our_hello;
+ plug->env.get_our_hello = &do_get_our_hello;
plug->env.cls = plug;
plug->env.receive = &plugin_env_receive;
plug->env.notify_address = &plugin_env_notify_address;
}
+static int
+null_mq_client_pointers (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct TransportClient *pos = cls;
+ struct NeighbourMapEntry *n = value;
+ struct MessageQueue *mq;
+
+ for (mq = n->messages_head; mq != NULL; mq = mq->next)
+ {
+ if (mq->client == pos)
+ mq->client = NULL; /* do not use anymore! */
+ }
+ return GNUNET_OK;
+}
+
+
/**
* Called whenever a client is disconnected. Frees our
* resources associated with that client.
pos->message_count--;
GNUNET_free (mqe);
}
+ if (NULL != neighbours)
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &null_mq_client_pointers,
+ pos);
if (prev == NULL)
clients = pos->next;
else
}
+static int
+disconnect_all_neighbours (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct NeighbourMapEntry *n = value;
+
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Disconnecting peer `%4s', %s\n",
+ GNUNET_i2s(&n->id),
+ "SHUTDOWN_TASK");
+#endif
+ disconnect_neighbour (n, GNUNET_NO);
+ return GNUNET_OK;
+}
+
+
/**
* Function called when the service shuts down. Unloads our plugins
* and cancels pending validations.
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct TransportPlugin *plug;
- struct TransportPlugin *tmp;
struct OwnAddressList *al;
struct CheckHelloValidatedContext *chvc;
shutdown_in_progress = GNUNET_YES;
- while (neighbours != NULL)
- {
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&neighbours->id),
- "SHUTDOWN_TASK");
-#endif
- disconnect_neighbour (neighbours, GNUNET_NO);
- }
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &disconnect_all_neighbours,
+ NULL);
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transport service is unloading plugins...\n");
#endif
- plug = plugins;
- while (plug != NULL)
+ while (NULL != (plug = plugins))
{
if (plug->address_update_task != GNUNET_SCHEDULER_NO_TASK)
{
plug->addresses = al->next;
GNUNET_free (al);
}
- tmp = plug->next;
+ plugins = plug->next;
GNUNET_free (plug);
- plug = tmp;
}
if (my_private_key != NULL)
GNUNET_CRYPTO_rsa_key_free (my_private_key);
GNUNET_SCHEDULER_cancel(ats_task);
ats_task = GNUNET_SCHEDULER_NO_TASK;
}
+#if HAVE_LIBGLPK
if (ats != NULL)
ats_shutdown (ats);
+#endif
/* free 'chvc' data structure */
while (NULL != (chvc = chvc_head))
explicitly!? */
GNUNET_break (bl_head == NULL);
GNUNET_break (bc_head == NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
}
}
-void create_ats_information ( struct ATS_peer **p,
- int * c_p,
- struct ATS_mechanism ** m,
- int * c_m )
+#if HAVE_LIBGLPK
+struct AtsBuildContext
{
-#if VERBOSE_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "ATS requires clean address information\n");
-#endif
struct ATS_mechanism * mechanisms;
struct ATS_peer *peers;
+ int c_peers;
+ int c_mechs;
+};
- int connected_addresses = 0;
- int c_peers = 0;
- int c_mechs = 0;
- struct NeighbourList *next = neighbours;
- while (next!=NULL)
- {
- int found_addresses = GNUNET_NO;
- struct ReadyList *r_next = next->plugins;
- while (r_next != NULL)
- {
- struct ForeignAddressList * a_next = r_next->addresses;
- while (a_next != NULL)
+static int
+find_and_count_addresses (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct AtsBuildContext *abc = cls;
+ struct NeighbourMapEntry *next = value;
+ int found_addresses = GNUNET_NO;
+
+ struct ReadyList *r_next = next->plugins;
+ while (r_next != NULL)
+ {
+ struct ForeignAddressList * a_next = r_next->addresses;
+ while (a_next != NULL)
{
- c_mechs++;
- found_addresses = GNUNET_YES;
- a_next = a_next->next;
+ abc->c_mechs++;
+ found_addresses = GNUNET_YES;
+ a_next = a_next->next;
}
- r_next = r_next->next;
+ r_next = r_next->next;
}
- if (found_addresses) c_peers++;
- next = next->next;
- }
+ if (found_addresses)
+ abc->c_peers++;
+ return GNUNET_OK;
+}
+
+
+static int
+setup_ats_problem (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct AtsBuildContext *abc = cls;
+ struct NeighbourMapEntry *next = value;
+
+ int found_addresses = GNUNET_NO;
+ struct ReadyList *r_next = next->plugins;
+ while (r_next != NULL)
+ {
+ struct ForeignAddressList * a_next = r_next->addresses;
+ while (a_next != NULL)
+ {
+ if (found_addresses == GNUNET_NO)
+ {
+ abc->peers[abc->c_peers].peer = next->id;
+ abc->peers[abc->c_peers].m_head = NULL;
+ abc->peers[abc->c_peers].m_tail = NULL;
+ abc->peers[abc->c_peers].f = 1.0 / abc->c_mechs;
+ }
+ abc->mechanisms[abc->c_mechs].addr = a_next;
+ abc->mechanisms[abc->c_mechs].col_index = abc->c_mechs;
+ abc->mechanisms[abc->c_mechs].peer = &abc->peers[abc->c_peers];
+ abc->mechanisms[abc->c_mechs].next = NULL;
+ abc->mechanisms[abc->c_mechs].plugin = r_next->plugin;
+ abc->mechanisms[abc->c_mechs].ressources = a_next->ressources;
+ abc->mechanisms[abc->c_mechs].quality = a_next->quality;
+ GNUNET_CONTAINER_DLL_insert_tail(abc->peers[abc->c_peers].m_head,
+ abc->peers[abc->c_peers].m_tail,
+ &abc->mechanisms[abc->c_mechs]);
+ found_addresses = GNUNET_YES;
+ abc->c_mechs++;
+ a_next = a_next->next;
+ }
+ r_next = r_next->next;
+ }
+ if (found_addresses == GNUNET_YES)
+ abc->c_peers++;
+ return GNUNET_OK;
+}
+
+
+static void
+create_ats_information ( struct ATS_peer **p,
+ int * c_p,
+ struct ATS_mechanism ** m,
+ int * c_m )
+{
+ struct AtsBuildContext abc;
+#if VERBOSE_ATS
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ATS requires clean address information\n");
+#endif
+ abc.c_peers = 0;
+ abc.c_mechs = 0;
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &find_and_count_addresses,
+ &abc);
#if VERBOSE_ATS
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Found %u peers with % u transport mechanisms\n", c_peers, c_mechs);
#endif
- if ((c_peers == 0) && (c_mechs == 0))
- {
- peers = NULL;
- (*c_p) = 0;
- mechanisms = NULL;
- (*c_m) = 0;
- return;
- }
-
- mechanisms = GNUNET_malloc((1+c_mechs) * sizeof (struct ATS_mechanism));
- peers = GNUNET_malloc((1+c_peers) * sizeof (struct ATS_peer));
-
- c_mechs = 1;
- c_peers = 1;
-
- next = neighbours;
- while (next!=NULL)
- {
- int found_addresses = GNUNET_NO;
- struct ReadyList *r_next = next->plugins;
- while (r_next != NULL)
+ if ( (abc.c_peers == 0) && (abc.c_mechs == 0) )
{
- struct ForeignAddressList * a_next = r_next->addresses;
- while (a_next != NULL)
- {
- if (a_next->connected == GNUNET_YES)
- connected_addresses ++;
- if (found_addresses == GNUNET_NO)
- {
- peers[c_peers].peer = next->id;
- peers[c_peers].m_head = NULL;
- peers[c_peers].m_tail = NULL;
- peers[c_peers].f = 1.0 / c_mechs;
- }
-
- mechanisms[c_mechs].addr = a_next;
- mechanisms[c_mechs].col_index = c_mechs;
- mechanisms[c_mechs].peer = &peers[c_peers];
- mechanisms[c_mechs].next = NULL;
- mechanisms[c_mechs].plugin = r_next->plugin;
- mechanisms[c_mechs].ressources = a_next->ressources;
- mechanisms[c_mechs].quality = a_next->quality;
-
- GNUNET_CONTAINER_DLL_insert_tail(peers[c_peers].m_head,
- peers[c_peers].m_tail,
- &mechanisms[c_mechs]);
- found_addresses = GNUNET_YES;
- c_mechs++;
-
- a_next = a_next->next;
- }
- r_next = r_next->next;
+ *p = NULL;
+ (*c_p) = 0;
+ *m = NULL;
+ (*c_m) = 0;
+ return;
}
- if (found_addresses == GNUNET_YES)
- c_peers++;
- next = next->next;
- }
- c_mechs--;
- c_peers--;
- (*c_m) = c_mechs;
- (*c_p) = c_peers;
- (*p) = peers;
- (*m) = mechanisms;
-
- GNUNET_STATISTICS_set(stats,
- gettext_noop ("# connected addresses"),
- connected_addresses,
- GNUNET_NO);
+
+ abc.mechanisms = GNUNET_malloc((1+abc.c_mechs) * sizeof (struct ATS_mechanism));
+ abc.peers = GNUNET_malloc((1+abc.c_peers) * sizeof (struct ATS_peer));
+ abc.c_mechs = 1;
+ abc.c_peers = 1;
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &setup_ats_problem,
+ &abc);
+ abc.c_mechs--;
+ abc.c_peers--;
+ (*c_m) = abc.c_mechs;
+ (*c_p) = abc.c_peers;
+ (*p) = abc.peers;
+ (*m) = abc.mechanisms;
}
+
static void
schedule_ats (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
#if DEBUG_ATS
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Running scheduled calculation\n");
#endif
- ats_calculate_bandwidth_distribution (ats, stats);
+#if HAVE_LIBGLPK
+ ats_calculate_bandwidth_distribution (ats);
+#endif
last_ats_execution = GNUNET_TIME_absolute_get();
ats_task = GNUNET_SCHEDULER_add_delayed (ats_regular_interval,
&schedule_ats, ats);
}
+#endif
+
struct ForeignAddressList * get_preferred_ats_address (
- struct NeighbourList *n)
+ struct NeighbourMapEntry *n)
{
// TODO get ATS prefered address
return find_ready_address(n);
cfg = c;
stats = GNUNET_STATISTICS_create ("transport", cfg);
validation_map = GNUNET_CONTAINER_multihashmap_create (64);
+ neighbours = GNUNET_CONTAINER_multihashmap_create (256);
/* parse configuration */
if ((GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (c,
}
GNUNET_CONTAINER_multihashmap_destroy (validation_map);
validation_map = NULL;
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
return;
}
}
GNUNET_CONTAINER_multihashmap_destroy (validation_map);
validation_map = NULL;
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
GNUNET_free (keyfile);
return;
}
}
GNUNET_CONTAINER_multihashmap_destroy (validation_map);
validation_map = NULL;
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
return;
}
GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
int co;
char * section;
unsigned long long value;
-
+#if HAVE_LIBGLPK
double D = 1.0;
double U = 1.0;
double R = 1.0;
int v_b_min = 64000;
int v_n_min = 5;
+#endif
ats_minimum_interval = ATS_MIN_INTERVAL;
ats_regular_interval = ATS_EXEC_INTERVAL;
}
GNUNET_free (section);
}
-
+#if HAVE_LIBGLPK
ats = ats_init (D, U, R, v_b_min, v_n_min,
ATS_MAX_ITERATIONS, ATS_MAX_EXEC_DURATION,
- create_ats_information,
+ &create_ats_information,
ats_result_cb);
-
- int log_problem = GNUNET_NO;
- int log_solution = GNUNET_NO;
- int overwrite_dump = GNUNET_NO;
- int minimum_peers = 0;
- int minimum_addresses = 0;
-
- if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_MLP"))
- log_problem = GNUNET_CONFIGURATION_get_value_yesno (cfg,
- "transport","DUMP_MLP");
-
- if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_SOLUTION"))
- log_solution = GNUNET_CONFIGURATION_get_value_yesno (cfg,
- "transport","DUMP_SOLUTION");
- if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_OVERWRITE"))
- overwrite_dump = GNUNET_CONFIGURATION_get_value_yesno (cfg,
- "transport","DUMP_OVERWRITE");
- if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "DUMP_MIN_PEERS"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","DUMP_MIN_PEERS", &value);
- minimum_peers = value;
- }
- if (GNUNET_CONFIGURATION_have_value(cfg,
- "transport", "DUMP_MIN_ADDRS"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","DUMP_MIN_ADDRS", &value);
- minimum_addresses= value;
- }
- if (GNUNET_CONFIGURATION_have_value(cfg,
- "transport", "DUMP_OVERWRITE"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","DUMP_OVERWRITE", &value);
- overwrite_dump = value;
- }
-
- if (GNUNET_CONFIGURATION_have_value(cfg,
- "transport", "ATS_MIN_INTERVAL"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","ATS_MIN_INTERVAL", &value);
- ats_minimum_interval.rel_value = value;
- }
-
- if (GNUNET_CONFIGURATION_have_value(cfg,
- "transport", "ATS_EXEC_INTERVAL"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","ATS_EXEC_INTERVAL", &value);
- ats_regular_interval.rel_value = value;
- }
- if (GNUNET_CONFIGURATION_have_value(cfg, "transport", "ATS_MIN_INTERVAL"))
- {
- GNUNET_CONFIGURATION_get_value_number(cfg,
- "transport","ATS_MIN_INTERVAL", &value);
- ats_minimum_interval.rel_value = value;
- }
-
ats_set_logging_options (ats,
- minimum_addresses,
- minimum_peers,
- overwrite_dump,
- log_solution,
- log_problem);
-
+ stats,
+ cfg);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ "transport",
+ "ATS_EXEC_INTERVAL",
+ &ats_regular_interval));
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ "transport",
+ "ATS_MIN_INTERVAL",
+ &ats_minimum_interval));
if (ats != NULL)
ats_task = GNUNET_SCHEDULER_add_now (&schedule_ats, ats);
-
-
+#endif
#if DEBUG_TRANSPORT