/** * Clean up node * * @param cls the peermap to clean up * @param key key of the current node * @param value related node object * @return always #GNUNET_OK */ static int cleanup_node (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct Node *n; struct NodeComCtx *e_cur; struct NodeComCtx *e_next; struct GNUNET_CONTAINER_MultiPeerMap *cur = cls; n = value; if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != n->cth) { GNUNET_CORE_notify_transmit_ready_cancel (n->cth); n->cth = NULL; } e_next = n->e_req_head; while (NULL != (e_cur = e_next)) { e_next = e_cur->next; GNUNET_CONTAINER_DLL_remove (n->e_req_head, n->e_req_tail, e_cur); GNUNET_free (e_cur); } GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (cur, key, value)); GNUNET_free (value); return GNUNET_OK; }
/** * Free all resources associated with the given peer. * * @param cls closure (not used) * @param pid identity of the peer * @param value peer to free * @return #GNUNET_YES (always: continue to iterate) */ static int free_peer (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) { struct Peer *pos = value; GNUNET_break (NULL == pos->mq); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (peers, pid, pos)); if (NULL != pos->hello_delay_task) { GNUNET_SCHEDULER_cancel (pos->hello_delay_task); pos->hello_delay_task = NULL; } if (NULL != pos->sh) { GNUNET_ATS_connectivity_suggest_cancel (pos->sh); pos->sh = NULL; } if (NULL != pos->hello) { GNUNET_free_non_null (pos->hello); pos->hello = NULL; } if (NULL != pos->filter) { GNUNET_CONTAINER_bloomfilter_free (pos->filter); pos->filter = NULL; } GNUNET_free (pos); return GNUNET_YES; }
/** * Release memory used by the given address data. * * @param ai the `struct AddressInfo` */ static void destroy_ai (struct AddressInfo *ai) { GNUNET_assert (NULL == ai->session); if (NULL != ai->unblock_task) { GNUNET_SCHEDULER_cancel (ai->unblock_task); ai->unblock_task = NULL; num_blocked--; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (p2a, &ai->address->peer, ai)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Telling ATS to destroy address from peer %s\n", GNUNET_i2s (&ai->address->peer)); if (NULL != ai->ar) { GNUNET_ATS_address_destroy (ai->ar); ai->ar = NULL; } publish_p2a_stat_update (); GNUNET_HELLO_address_free (ai->address); GNUNET_free (ai); }
/** * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels * any pending transmission requests to that peer. * * @param cls closure * @param peer peer identity this notification is about * @parma internal_cls the `struct NSEPeerEntry` for the @a peer */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls) { struct NSEPeerEntry *pos = internal_cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected from us\n", GNUNET_i2s (peer)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos)); if (NULL != pos->transmit_task) { GNUNET_SCHEDULER_cancel (pos->transmit_task); pos->transmit_task = NULL; } GNUNET_free (pos); GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); }
/** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, value)); return GNUNET_YES; }
/** * Free `struct PreferencePeer` entry in map. * * @param cls the `struct PreferenceClient` with the map * @param key the peer the entry is for * @param value the `struct PreferencePeer` entry to free * @return #GNUNET_OK (continue to iterate) */ static int free_preference (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct PreferenceClient *pc = cls; struct PreferencePeer *p = value; struct PeerRelative *pr; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (pc->peer2pref, key, p)); GNUNET_free (p); pr = GNUNET_CONTAINER_multipeermap_get (preference_peers, key); GNUNET_assert (NULL != pr); GNUNET_assert (pr->num_clients > 0); pr->num_clients--; if (0 == pr->num_clients) { free_peer (NULL, key, pr); } return GNUNET_OK; }
int destroy_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MonitoredPeer *m = value; GNUNET_CONTAINER_multipeermap_remove (monitored_peers, key, value); GNUNET_free_non_null (m->address); GNUNET_free (value); return GNUNET_OK; }
/** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current public key * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int free_iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Entry *e = cls; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, e)); GNUNET_free (e); return GNUNET_YES; }
/** * Handler called by CORE when CORE is ready to transmit message * * @param cls closure with the `const struct GNUNET_PeerIdentity *` of * the peer we are sending to * @param size size of buffer to copy message to * @param buf buffer to copy message to * @return number of bytes copied to @a buf */ static size_t adv_transmit_ready (void *cls, size_t size, void *buf) { const struct GNUNET_PeerIdentity *peer = cls; static uint64_t hostlist_adv_count; size_t transmission_size; size_t uri_size; /* Including \0 termination! */ struct GNUNET_MessageHeader header; char *cbuf; struct GNUNET_CORE_TransmitHandle *th; th = GNUNET_CONTAINER_multipeermap_get (advertisements, peer); GNUNET_assert (NULL != th); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (advertisements, peer, th)); if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, buffer invalid!\n"); return 0; } uri_size = strlen (hostlist_uri) + 1; transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size; header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT); header.size = htons (transmission_size); GNUNET_assert (size >= transmission_size); memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader)); cbuf = buf; memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent advertisement message: Copied %u bytes into buffer!\n", (unsigned int) transmission_size); hostlist_adv_count++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n", hostlist_adv_count); GNUNET_STATISTICS_update (stats, gettext_noop ("# hostlist advertisements send"), 1, GNUNET_NO); return transmission_size; }
/** * Free a peer's `struct PeerRelative`. * * @param cls unused * @param key the key * @param value the `struct PeerRelative` to free. * @return #GNUNET_OK to continue */ static int free_peer (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct PeerRelative *rp = value; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (preference_peers, key, value)); GNUNET_free (rp); return GNUNET_OK; }
/** * End the session with the given peer (we are no longer * connected). * * @param pid identity of peer to kill session with */ void GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid) { struct Session *session; struct GSC_ClientActiveRequest *car; struct SessionMessageEntry *sme; session = find_session (pid); if (NULL == session) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying session for peer `%4s'\n", GNUNET_i2s (&session->peer)); if (NULL != session->cork_task) { GNUNET_SCHEDULER_cancel (session->cork_task); session->cork_task = NULL; } while (NULL != (car = session->active_client_request_head)) { GNUNET_CONTAINER_DLL_remove (session->active_client_request_head, session->active_client_request_tail, car); GSC_CLIENTS_reject_request (car, GNUNET_NO); } while (NULL != (sme = session->sme_head)) { GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme); GNUNET_free (sme); } if (NULL != session->typemap_task) { GNUNET_SCHEDULER_cancel (session->typemap_task); session->typemap_task = NULL; } GSC_CLIENTS_notify_clients_about_neighbour (&session->peer, session->tmap, NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (sessions, &session->peer, session)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (sessions), GNUNET_NO); GSC_TYPEMAP_destroy (session->tmap); session->tmap = NULL; GNUNET_free (session); }
/** * Free `struct AddressInformationData` entry. * * @param cls NULL * @param key ignored * @param value the `struct AddressSuggestData` to release * @return #GNUNET_OK (continue to iterate) */ static int free_aid (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct AddressInformationData *aid = value; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (p2aid, key, aid)); GNUNET_free (aid->address); GNUNET_free (aid); return GNUNET_OK; }
/** * Free `struct AddressSuggestData` entry. * * @param cls NULL * @param key ignored * @param value the `struct AddressSuggestData` to release * @return #GNUNET_OK (continue to iterate) */ static int free_asd (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct AddressSuggestData *asd = value; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (p2asd, key, asd)); GNUNET_free_non_null (asd->address); GNUNET_free (asd); return GNUNET_OK; }
/** * Free the given entry for the neighbour. * * @param n neighbour to free */ static void free_neighbour (struct Neighbour *n) { struct NeighbourMessageEntry *m; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying neighbour entry for peer `%s'\n", GNUNET_i2s (&n->peer)); while (NULL != (m = n->message_head)) { GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m); n->queue_size--; GNUNET_free (m); } GNUNET_assert (0 == n->queue_size); if (NULL != n->th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th); n->th = NULL; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# sessions terminated by transport disconnect"), 1, GNUNET_NO); if (NULL != n->kxinfo) { GSC_KX_stop (n->kxinfo); n->kxinfo = NULL; } if (NULL != n->retry_plaintext_task) { GNUNET_SCHEDULER_cancel (n->retry_plaintext_task); n->retry_plaintext_task = NULL; } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (neighbours, &n->peer, n)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"), GNUNET_CONTAINER_multipeermap_size (neighbours), GNUNET_NO); GNUNET_free (n); }
/** * 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; }
/** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GNUNET_CORE_TransmitHandle *th; if (! advertising) return; th = GNUNET_CONTAINER_multipeermap_get (advertisements, peer); if (NULL == th) return; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (advertisements, peer, th)); GNUNET_CORE_notify_transmit_ready_cancel (th); }
/** * Notify clients about disconnect and free * the entry for connected peer. * * @param cls the `struct GNUNET_CORE_Handle *` * @param key the peer identity (not used) * @param value the `struct PeerRecord` to free. * @return #GNUNET_YES (continue) */ static int disconnect_and_free_peer_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_CORE_Handle *h = cls; struct GNUNET_CORE_TransmitHandle *th; struct PeerRecord *pr = value; if (GNUNET_SCHEDULER_NO_TASK != pr->timeout_task) { GNUNET_SCHEDULER_cancel (pr->timeout_task); pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != pr->ntr_task) { GNUNET_SCHEDULER_cancel (pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; } if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr)) GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); if (NULL != h->disconnects) h->disconnects (h->cls, &pr->peer); /* all requests should have been cancelled, clean up anyway, just in case */ th = &pr->th; if (NULL != th->peer) { GNUNET_break (0); th->peer = NULL; if (NULL != th->cm) th->cm->th = NULL; } /* done with 'voluntary' cleanups, now on to normal freeing */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (h->peers, key, pr)); GNUNET_assert (pr->ch == h); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->timeout_task); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task); GNUNET_free (pr); return GNUNET_YES; }
/** * Free the connection request from the map if the * closure matches the client. * * @param cls the client to match * @param pid peer for which the request was made * @param value the `struct ConnectionRequest` * @return #GNUNET_OK (continue to iterate) */ static int free_matching_requests (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) { struct GNUNET_SERVER_Client *client = cls; struct ConnectionRequest *cr = value; if (cr->client == client) { GAS_plugin_request_connect_stop (pid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removed request pending for peer `%s\n", GNUNET_i2s (pid)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (connection_requests, pid, cr)); GNUNET_free (cr); } return GNUNET_OK; }
/** * We got disconnected from the service and thus all of the * pending send callbacks will never be confirmed. Clean up. * * @param cls the 'struct GNUNET_DV_ServiceHandle' * @param key a peer identity * @param value a `struct ConnectedPeer` to clean up * @return #GNUNET_OK (continue to iterate) */ static int cleanup_send_cb (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_DV_ServiceHandle *sh = cls; struct ConnectedPeer *peer = value; struct GNUNET_DV_TransmitHandle *th; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (sh->peers, key, peer)); sh->disconnect_cb (sh->cls, key); while (NULL != (th = peer->head)) { GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, th); th->cb (th->cb_cls, GNUNET_SYSERR); GNUNET_free (th); } GNUNET_free (peer); return GNUNET_OK; }
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; }
/** * Handle a request and send a response * * @param peer the source * @param message the message */ static void handle_request (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct Node *n; struct NodeComCtx *e_ctx; const struct Experimentation_Request *rm = (const struct Experimentation_Request *) message; const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1]; unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers); int c1; int c2; uint32_t ic; uint32_t ic_accepted; int make_active; if (ntohs (message->size) < sizeof (struct Experimentation_Request)) { GNUNET_break (0); return; } ic = ntohl (rm->issuer_count); if (ntohs (message->size) != sizeof (struct Experimentation_Request) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) { GNUNET_break (0); return; } make_active = GNUNET_NO; if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) { /* Nothing to do */ } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n)); if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } update_stats (nodes_requested); make_active = GNUNET_YES; } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) { GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n)); update_stats (nodes_inactive); make_active = GNUNET_YES; } else { /* Create new node */ n = GNUNET_new (struct Node); n->id = *peer; n->capabilities = NONE; make_active = GNUNET_YES; } /* Update node */ n->capabilities = ntohl (rm->capabilities); /* Filter accepted issuer */ ic_accepted = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) ic_accepted ++; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request from peer `%s' with %u issuers, we accepted %u issuer \n", GNUNET_i2s (peer), ic, ic_accepted); GNUNET_free_non_null (n->issuer_id); n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); c2 = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted (&rmi[c1])) { n->issuer_id[c2] = rmi[c1]; c2 ++; } } n->issuer_count = ic_accepted; if (GNUNET_YES == make_active) node_make_active (n); /* Send response */ e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = NULL; e_ctx->size = sizeof (struct Experimentation_Response) + my_issuer_count * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); e_ctx->notify = &send_response_cb; e_ctx->notify_cls = n; GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx); schedule_transmisson (e_ctx); }
/** * Handle a response * * @param peer the source * @param message the message */ static void handle_response (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct Node *n; const struct Experimentation_Response *rm = (const struct Experimentation_Response *) message; const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1]; uint32_t ic; uint32_t ic_accepted; int make_active; unsigned int c1; unsigned int c2; if (ntohs (message->size) < sizeof (struct Experimentation_Response)) { GNUNET_break (0); return; } ic = ntohl (rm->issuer_count); if (ntohs (message->size) != sizeof (struct Experimentation_Response) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) { GNUNET_break (0); return; } make_active = GNUNET_NO; if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "active", GNUNET_i2s (peer)); } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "requested", GNUNET_i2s (peer)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n)); if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } update_stats (nodes_requested); make_active = GNUNET_YES; } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from peer `%s'\n", "RESPONSE", "inactive", GNUNET_i2s (peer)); GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n)); update_stats (nodes_inactive); make_active = GNUNET_YES; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "unknown", GNUNET_i2s (peer)); return; } /* Update */ n->capabilities = ntohl (rm->capabilities); /* Filter accepted issuer */ ic_accepted = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) ic_accepted ++; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Response from peer `%s' with %u issuers, we accepted %u issuer \n", GNUNET_i2s (peer), ic, ic_accepted); GNUNET_free_non_null (n->issuer_id); n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_PeerIdentity)); c2 = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) { n->issuer_id[c2] = rmi[c1]; c2 ++; } } n->issuer_count = ic_accepted; if (GNUNET_YES == make_active) node_make_active (n); }