/** * FIXME: Change the name of variable. * Ensure that everywhere in this file you are using destination as the key. * Do we need prev field in routing table? * Add a new entry to our routing table. * @param source peer * @param destintation * @param next_hop */ void GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, struct GNUNET_PeerIdentity *dest, struct GNUNET_PeerIdentity *next_hop) { struct RoutingTrail *new_routing_entry; new_routing_entry = GNUNET_malloc (sizeof (struct RoutingTrail)); new_routing_entry->source = source; new_routing_entry->next_hop = next_hop; new_routing_entry->destination = dest; /* If dest is already present in the routing table, then exit.*/ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (routing_table, dest)) { GNUNET_break (0); return; } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (routing_table, dest, new_routing_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); }
/** * Check if the given peer is currently connected. This function is for special * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are * expected to track which peers are connected based on the connect/disconnect * callbacks from GNUNET_CORE_connect. This function is NOT part of the * 'versioned', 'official' API. The difference between this function and the * function GNUNET_CORE_is_peer_connected() is that this one returns * synchronously after looking in the CORE API cache. The function * GNUNET_CORE_is_peer_connected() sends a message to the CORE service and hence * its response is given asynchronously. * * @param h the core handle * @param pid the identity of the peer to check if it has been connected to us * @return GNUNET_YES if the peer is connected to us; GNUNET_NO if not */ int GNUNET_CORE_is_peer_connected_sync (const struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *pid) { GNUNET_assert (NULL != h); GNUNET_assert (NULL != pid); return GNUNET_CONTAINER_multipeermap_contains (h->peers, pid); }
/** * Is the given peer in the list of peers for which we * have an address request? * * @param cls unused, NULL * @param peer peer to query for * @return #GNUNET_YES if so, #GNUNET_NO if not */ unsigned int GAS_connectivity_has_peer (void *cls, const struct GNUNET_PeerIdentity *peer) { if (NULL == connection_requests) return 0; /* TODO: return sum of 'strength's of connectivity requests */ return GNUNET_CONTAINER_multipeermap_contains (connection_requests, peer); }
/** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { if (GNUNET_YES == is_me(peer)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to peer %s\n"), GNUNET_i2s (peer)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, peer)) return; /* We already sent a request */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_active, peer)) return; /* This peer is known as active */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_inactive, peer)) return; /* This peer is known as inactive */ send_experimentation_request (peer); }
/** * @brief Get the #PeerContext associated with a peer * * @param peer the peer id * * @return the #PeerContext */ static struct PeerContext * get_peer_ctx (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *ctx; int ret; ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer); GNUNET_assert (GNUNET_YES == ret); ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer); GNUNET_assert (NULL != ctx); return ctx; }
/** * Function that decides if a connection is acceptable or not. * * @param cls closure * @param pid peer to approve or disapproave * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not */ static int check_access (void *cls, const struct GNUNET_PeerIdentity * pid) { int contains; GNUNET_assert (NULL != map); contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); if (GNUNET_YES == contains) { DEBUG ("Permitting `%s'\n", GNUNET_i2s (pid)); return GNUNET_OK; } DEBUG ("Not permitting `%s'\n", GNUNET_i2s (pid)); return GNUNET_SYSERR; }
/** * Clear the custom peer map * * @param c_peer_map the custom peer map to look in * * @return size of the map */ void View_clear () { uint32_t i; uint32_t *index; for (i = 0; 0 < View_size (); i++) { /* Need to free indices stored at peers */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (mpm, &array[i])); index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]); GNUNET_assert (NULL != index); GNUNET_free (index); GNUNET_CONTAINER_multipeermap_remove_all (mpm, &array[i]); } GNUNET_assert (0 == View_size ()); }
/** * Remove experimentation request due to timeout * * @param cls the related node * @param tc scheduler's task context */ static void remove_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Node *n = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing request for peer %s due to timeout\n", GNUNET_i2s (&n->id)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, &n->id)) { GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, &n->id, n)); update_stats (nodes_requested); GNUNET_CONTAINER_multipeermap_put (nodes_inactive, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); update_stats (nodes_inactive); } n->timeout_task = GNUNET_SCHEDULER_NO_TASK; }
/** * @brief Check if peer is removable. * * Check if * - a recv channel exists * - there are pending messages * - there is no pending pull reply * * @param peer the peer in question * @return #GNUNET_YES if peer is removable * #GNUNET_NO if peer is NOT removable * #GNUNET_SYSERR if peer is not known */ int Peers_check_removable (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *peer_ctx; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) { return GNUNET_SYSERR; } peer_ctx = get_peer_ctx (peer); if ( (NULL != peer_ctx->recv_channel) || (NULL != peer_ctx->pending_messages_head) || (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) ) { return GNUNET_NO; } return GNUNET_YES; }
/** * Send a message to all of our current clients that have the right * options set. * * @param partner origin (or destination) of the message (used to check that this peer is * known to be connected to the respective client) * @param msg message to multicast * @param can_drop can this message be discarded if the queue is too long * @param options mask to use * @param type type of the embedded message, 0 for none */ static void send_to_all_clients (const struct GNUNET_PeerIdentity *partner, const struct GNUNET_MessageHeader *msg, int can_drop, uint32_t options, uint16_t type) { struct GSC_Client *c; int tm; for (c = client_head; NULL != c; c = c->next) { tm = type_match (type, c); if (! ( (0 != (c->options & options)) || ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) && (GNUNET_YES == tm) ) ) ) continue; /* neither options nor type match permit the message */ if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) && ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES == tm) ) ) continue; if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) continue; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u message with %u bytes to client interested in messages of type %u.\n", options, ntohs (msg->size), (unsigned int) type); GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES != tm) || (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (c->connectmap, partner)) ); send_to_client (c, msg, can_drop); } }
/** * Search callback function called when a subscribed peer is found. * * @param cls closure provided in GNUNET_REGEX_search() * @param id peer providing a regex that matches the string * @param get_path path of the get request * @param get_path_length length of @a get_path * @param put_path Path of the put request * @param put_path_length length of the @a put_path */ static void subscribed_peer_found (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct PendingMessage *pm; struct RemoteSubscriberInfo *subscriber; struct GNUNET_MessageHeader *msg; struct RegexSearchContext *context = cls; size_t msg_len = ntohs (context->publish_msg->header.size); LOG (GNUNET_ERROR_TYPE_DEBUG, "--------> Found an active subscription from %s\n", GNUNET_i2s (id)); /* * We may have delivered the message to the peer already if it has * other matching subscriptions; ignore this search result if that is * the case. */ if (GNUNET_CONTAINER_multipeermap_contains (context->subscribers, id)) return; GNUNET_CONTAINER_multipeermap_put (context->subscribers, id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); subscriber = GNUNET_CONTAINER_multipeermap_get (remote_subscribers, id); if (0 == memcmp (id, &my_id, sizeof (struct GNUNET_PeerIdentity))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "fast tracking PUBLISH message to local subscribers\n"); deliver_incoming_publish (context->publish_msg, context); return; } msg = GNUNET_malloc (msg_len); memcpy (msg, context->publish_msg, msg_len); pm = GNUNET_new (struct PendingMessage); pm->msg = msg; pm->context = context; if (NULL == subscriber) { LOG (GNUNET_ERROR_TYPE_DEBUG, "creating a new channel to %s\n", GNUNET_i2s(id)); subscriber = GNUNET_new (struct RemoteSubscriberInfo); subscriber->channel = GNUNET_MESH_channel_create (mesh_handle, NULL, id, GNUNET_APPLICATION_TYPE_MQTT, GNUNET_MESH_OPTION_RELIABLE); subscriber->peer_added = GNUNET_NO; subscriber->peer_connecting = GNUNET_NO; subscriber->id = *id; GNUNET_CONTAINER_multipeermap_put (remote_subscribers, id, subscriber, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); }
/** * Check whether view contains a peer * * @param peer the peer to check for * * @return GNUNET_OK if view contains peer * GNUNET_NO otherwise */ int View_contains_peer (const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_contains (mpm, peer); }
/** * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message. * * @param cls unused * @param client new client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST * @param message the `struct SendMessageRequest` (presumably) */ static void handle_client_send_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct SendMessageRequest *req; struct GSC_Client *c; struct GSC_ClientActiveRequest *car; int is_loopback; req = (const struct SendMessageRequest *) message; c = find_client (client); if (NULL == c) { /* client did not send INIT first! */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (NULL == c->requests) c->requests = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client asked for transmission to `%s'\n", GNUNET_i2s (&req->peer)); is_loopback = (0 == memcmp (&req->peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))); if ((! is_loopback) && (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &req->peer))) { /* neighbour must have disconnected since request was issued, * ignore (client will realize it once it processes the * disconnect notification) */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# send requests dropped (disconnected)"), 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } car = GNUNET_CONTAINER_multipeermap_get (c->requests, &req->peer); if (NULL == car) { /* create new entry */ car = GNUNET_new (struct GSC_ClientActiveRequest); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (c->requests, &req->peer, car, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); car->client_handle = c; }
/** * @brief Remove peer * * @param peer the peer to clean * @return #GNUNET_YES if peer was removed * #GNUNET_NO otherwise */ int Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *peer_ctx; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) { return GNUNET_NO; } peer_ctx = get_peer_ctx (peer); set_peer_flag (peer_ctx, Peers_TO_DESTROY); LOG (GNUNET_ERROR_TYPE_DEBUG, "Going to remove peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); Peers_unset_peer_flag (peer, Peers_ONLINE); GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); while (NULL != peer_ctx->pending_messages_head) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing unsent %s\n", peer_ctx->pending_messages_head->type); remove_pending_message (peer_ctx->pending_messages_head); } /* If we are still waiting for notification whether this peer is live * cancel the according task */ if (NULL != peer_ctx->liveliness_check_pending) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing pending liveliness check for peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); // TODO wait until cadet sets mq->cancel_impl //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev); GNUNET_free (peer_ctx->liveliness_check_pending); peer_ctx->liveliness_check_pending = NULL; } if (NULL != peer_ctx->send_channel) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying send channel\n"); GNUNET_CADET_channel_destroy (peer_ctx->send_channel); peer_ctx->send_channel = NULL; } if (NULL != peer_ctx->recv_channel) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying recv channel\n"); GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); peer_ctx->recv_channel = NULL; } if (NULL != peer_ctx->mq) { GNUNET_MQ_destroy (peer_ctx->mq); peer_ctx->mq = NULL; } GNUNET_free (peer_ctx->send_channel_flags); GNUNET_free (peer_ctx->recv_channel_flags); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id)) { LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n"); } GNUNET_free (peer_ctx); return GNUNET_YES; }
/** * Signature of a function that is called with QoS information about an address. * * @param cls closure * @param address the address * @param address_active is this address actively used to maintain a connection * to a peer * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in 'ats' */ static void addr_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static const char *query_insert = "INSERT INTO ats_info(" " id," " val," " timestamp" ") VALUES (" " ?1," " ?2," " datetime('now')" ");"; struct Entry *entry; int latency; unsigned int cnt; GNUNET_assert (NULL != db); if (GNUNET_NO == address_active) return; for (cnt = 0; cnt < ats_count; cnt++) { if (GNUNET_ATS_QUALITY_NET_DELAY == ntohl (ats[cnt].type)) goto insert; } return; insert: latency = (int) ntohl (ats[cnt].value); entry = NULL; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map, &address->peer)) { entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer); GNUNET_assert (NULL != entry); if (latency == entry->latency) return; } if (NULL == stmt_insert) { if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); goto err_shutdown; } } if ( (SQLITE_OK != sqlite3_bind_text (stmt_insert, 1, GNUNET_i2s (&address->peer), -1, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency)) ) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text"); goto err_shutdown; } if (SQLITE_DONE != sqlite3_step (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); goto err_shutdown; } if (SQLITE_OK != sqlite3_reset (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert"); goto err_shutdown; } if (NULL == entry) { entry = GNUNET_new (struct Entry); entry->id = address->peer; GNUNET_CONTAINER_multipeermap_put (map, &entry->id, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); }
/** * @brief Check whether @a peer is actually a peer. * * A valid peer is a peer that we know exists eg. we were connected to once. * * @param peer peer in question * * @return #GNUNET_YES if peer is valid * #GNUNET_NO if peer is not valid */ int Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer); }
/** * @brief Check whether we have information about the given peer. * * FIXME probably deprecated. Make this the new _online. * * @param peer peer in question * * @return #GNUNET_YES if peer is known * #GNUNET_NO if peer is not knwon */ int Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer); }
static int testMap (int i) { struct GNUNET_CONTAINER_MultiPeerMap *m; struct GNUNET_PeerIdentity k1; struct GNUNET_PeerIdentity k2; struct GNUNET_CONTAINER_MultiPeerMapIterator *iter; struct GNUNET_PeerIdentity key_ret; const char *ret; int j; CHECK (NULL != (m = GNUNET_CONTAINER_multipeermap_create (i, GNUNET_NO))); memset (&k1, 0, sizeof (k1)); memset (&k2, 1, sizeof (k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k1, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k2, NULL)); CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k1)); CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k2)); CHECK (0 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1)); CHECK (0 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (0 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m)); ret = GNUNET_CONTAINER_multipeermap_get (m, &k1); GNUNET_assert (ret != NULL); CHECK (0 == strcmp ("v1", ret)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v3", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (3 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (m, &k1, "v3")); CHECK (2 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2)); CHECK (2 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k2, NULL, NULL)); CHECK (2 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL)); iter = GNUNET_CONTAINER_multipeermap_iterator_create (m); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); CHECK (2 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1)); for (j = 0; j < 1024; j++) CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); iter = GNUNET_CONTAINER_multipeermap_iterator_create (m); for (j = 0; j < GNUNET_CONTAINER_multipeermap_size (m); j++) CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); GNUNET_CONTAINER_multipeermap_destroy (m); return 0; }
/** * Signature of a function that is called with QoS information about an address. * * @param cls closure * @param address the address * @param address_active #GNUNET_YES if this address is actively used * to maintain a connection to a peer; * #GNUNET_NO if the address is not actively used; * #GNUNET_SYSERR if this address is no longer available for ATS * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param prop performance data for the address (as far as known) */ static void addr_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Properties *prop) { static const char *query_insert = "INSERT INTO ats_info(" " id," " val," " timestamp" ") VALUES (" " ?1," " ?2," " datetime('now')" ");"; struct Entry *entry; int latency; /* FIXME: type!? */ if (NULL == address) { /* ATS service temporarily disconnected */ return; } GNUNET_assert (NULL != db); if (GNUNET_YES != address_active) return; latency = (int) prop->delay.rel_value_us; entry = NULL; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map, &address->peer)) { entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer); GNUNET_assert (NULL != entry); if (latency == entry->latency) return; } if (NULL == stmt_insert) { if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); goto err_shutdown; } } if ( (SQLITE_OK != sqlite3_bind_text (stmt_insert, 1, GNUNET_i2s (&address->peer), -1, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency)) ) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text"); goto err_shutdown; } if (SQLITE_DONE != sqlite3_step (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); goto err_shutdown; } if (SQLITE_OK != sqlite3_reset (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert"); goto err_shutdown; } if (NULL == entry) { entry = GNUNET_new (struct Entry); entry->id = address->peer; GNUNET_CONTAINER_multipeermap_put (map, &entry->id, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); }