/** * Do pre-calculation for ECC discrete logarithm for small factors. * * @param max maximum value the factor can be * @param mem memory to use (should be smaller than @a max), must not be zero. * @return @a max if dlog failed, otherwise the factor */ struct GNUNET_CRYPTO_EccDlogContext * GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem) { struct GNUNET_CRYPTO_EccDlogContext *edc; unsigned int K = ((max + (mem-1)) / mem); gcry_mpi_point_t g; struct GNUNET_PeerIdentity key; gcry_mpi_point_t gKi; gcry_mpi_t fact; gcry_mpi_t n; unsigned int i; GNUNET_assert (max < INT32_MAX); edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); edc->max = max; edc->mem = mem; edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, GNUNET_NO); GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); gKi = gcry_mpi_point_new (0); for (i=0;i<=mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) i + max, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } /* negative values */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); for (i=1;i<mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_sub (fact, n, fact); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) max - i, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (gKi); gcry_mpi_point_release (g); return edc; }
/** * 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)); }
/** * Change length of view * * If size is decreased, peers with higher indices are removed. * * @param len the (maximum) length for the view */ void View_change_len (uint32_t len) { uint32_t i; uint32_t *index; if (GNUNET_CONTAINER_multipeermap_size (mpm) < len) { /* Simply shrink */ /* We might simply clear and free the left over space */ GNUNET_array_grow (array, length, len); } else /* We have to remove elements */ { /* TODO find a way to preserve indices */ for (i = 0; i < len; i++) { index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]); GNUNET_assert (NULL != index); GNUNET_free (index); } GNUNET_array_grow (array, length, len); GNUNET_CONTAINER_multipeermap_destroy (mpm); mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO); for (i = 0; i < len; i++) { index = GNUNET_new (uint32_t); *index = i; GNUNET_CONTAINER_multipeermap_put (mpm, &array[i], index, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } } GNUNET_assert (length == len); }
/** * Send request to peer to start add him to to the set of experimentation nodes * * @param peer the peer to send to */ static void send_experimentation_request (const struct GNUNET_PeerIdentity *peer) { struct Node *n; struct NodeComCtx *e_ctx; size_t size; size_t c_issuers; c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers); size = sizeof (struct Experimentation_Request) + c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); n = GNUNET_new (struct Node); n->id = *peer; n->timeout_task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &remove_request, n); n->capabilities = NONE; e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = NULL; e_ctx->size = size; e_ctx->notify = &send_experimentation_request_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); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (nodes_requested, peer, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); update_stats (nodes_requested); }
/** * Function called with information about a peers * * @param cls closure * @param peer identity of the peer, NULL for final callback when operation done * @param address binary address used to communicate with this peer, * NULL on disconnect or when done * @param state current state this peer is in * @param state_timeout time out for the current state * */ static void process_peer_monitoring_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { struct MonitoredPeer *m; if (peer == NULL ) { /* done */ address_resolution_in_progress = GNUNET_NO; pic = NULL; if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if (GNUNET_SCHEDULER_NO_TASK != op_timeout) GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer))) { m = GNUNET_new (struct MonitoredPeer); GNUNET_CONTAINER_multipeermap_put (monitored_peers, peer, m, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); }
/** * Create a session, a key exchange was just completed. * * @param peer peer that is now connected * @param kx key exchange that completed */ void GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx) { struct Session *session; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating session for peer `%4s'\n", GNUNET_i2s (peer)); session = GNUNET_new (struct Session); session->tmap = GSC_TYPEMAP_create (); session->peer = *peer; session->kxinfo = kx; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (sessions, &session->peer, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (sessions), GNUNET_NO); GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, session->tmap); start_typemap_task (session); }
/** * Add a host to the list and notify clients about this event * * @param identity the identity of the host * @return the HostEntry */ static struct HostEntry * add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) { struct HostEntry *entry; struct ReadHostFileContext r; char *fn; entry = GNUNET_CONTAINER_multipeermap_get (hostmap, identity); if (NULL == entry) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding new peer `%s'\n", GNUNET_i2s (identity)); GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1, GNUNET_NO); entry = GNUNET_new (struct HostEntry); entry->identity = *identity; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (hostmap, &entry->identity, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); notify_all (entry); fn = get_host_filename (identity); if (NULL != fn) { read_host_file (fn, GNUNET_YES, &r); if (NULL != r.hello) update_hello (identity, r.hello); if (NULL != r.friend_only_hello) update_hello (identity, r.friend_only_hello); GNUNET_free_non_null (r.hello); GNUNET_free_non_null (r.friend_only_hello); GNUNET_free (fn); } }
/** * Notify ATS about a new inbound @a address. The @a address in * combination with the @a session must be new, but this function will * perform a santiy check. If the @a address is indeed new, make it * available to ATS. * * @param address the address * @param session the session * @param prop performance information */ void GST_ats_add_inbound_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, const struct GNUNET_ATS_Properties *prop) { struct GNUNET_ATS_AddressRecord *ar; struct AddressInfo *ai; if (0 == memcmp (&GST_my_identity, &address->peer, sizeof (struct GNUNET_PeerIdentity))) return; /* our own, ignore! */ /* Sanity checks for a valid inbound address */ if (NULL == address->transport_name) { GNUNET_break(0); return; } GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != prop->scope); GNUNET_assert (GNUNET_YES == GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)); GNUNET_assert (NULL != session); ai = find_ai (address, session); if (NULL != ai) { /* This should only be called for new sessions, and thus we should not already have the address */ GNUNET_break (0); return; } /* Is indeed new, let's tell ATS */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Notifying ATS about peer `%s''s new inbound address `%s' session %p in network %s\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address), session, GNUNET_ATS_print_network_type (prop->scope)); ar = GNUNET_ATS_address_add (GST_ats, address, session, prop); GNUNET_assert (NULL != ar); ai = GNUNET_new (struct AddressInfo); ai->address = GNUNET_HELLO_address_copy (address); ai->session = session; ai->properties = *prop; ai->ar = ar; (void) GNUNET_CONTAINER_multipeermap_put (p2a, &ai->address->peer, ai, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); publish_p2a_stat_update (); }
/** * Create an address for a peer * * @param cp index of the peer * @param ca index of the address * @return the address */ static struct ATS_Address * perf_create_address (int cp, int ca) { struct ATS_Address *a; a = create_address (&ph.peers[cp].id, "Test 1", "test 1", strlen ("test 1") + 1, 0); GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); return a; }
/** * Set a specific node as active * * @param n the node */ static void node_make_active (struct Node *n) { int c1; GNUNET_CONTAINER_multipeermap_put (nodes_active, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); update_stats (nodes_active); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Added peer `%s' as active node\n"), GNUNET_i2s (&n->id)); /* Request experiments for this node to start them */ for (c1 = 0; c1 < n->issuer_count; c1++) { GED_experiments_get (n, &n->issuer_id[c1], &get_experiments_cb); } }
/** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { size_t size; struct GNUNET_CORE_TransmitHandle *th; if (! advertising) return; if (NULL == hostlist_uri) return; size = strlen (hostlist_uri) + 1; if (size + sizeof (struct GNUNET_MessageHeader) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } size += sizeof (struct GNUNET_MessageHeader); if (NULL == core) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked CORE to transmit advertisement message with a size of %u bytes to peer `%s'\n", size, GNUNET_i2s (peer)); if (NULL == (th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_ADV_TIMEOUT, peer, size, &adv_transmit_ready, (void *) peer)) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Advertisement message could not be queued by core\n")); } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (advertisements, peer, th, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); }
/** * @brief Add a given @a peer to valid peers. * * If valid peers are already #num_valid_peers_max, delete a peer previously. * * @param peer the peer that is added to the valid peers. * * @return #GNUNET_YES if no other peer had to be removed * #GNUNET_NO otherwise */ static int add_valid_peer (const struct GNUNET_PeerIdentity *peer) { const struct GNUNET_PeerIdentity *rand_peer; int ret; ret = GNUNET_YES; while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max) { rand_peer = get_random_peer_from_peermap (valid_peers); GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer); ret = GNUNET_NO; } (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); return ret; }
/** * @brief Create a new #PeerContext and insert it into the peer map * * @param peer the peer to create the #PeerContext for * * @return the #PeerContext */ static struct PeerContext * create_peer_ctx (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *ctx; int ret; GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer)); ctx = GNUNET_new (struct PeerContext); ctx->peer_id = *peer; ctx->send_channel_flags = GNUNET_new (uint32_t); ctx->recv_channel_flags = GNUNET_new (uint32_t); ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); GNUNET_assert (GNUNET_OK == ret); return ctx; }
/** * Notify ATS about the new address including the network this address is * located in. The address must NOT be inbound and must be new to ATS. * * @param address the address * @param prop performance information */ void GST_ats_add_address (const struct GNUNET_HELLO_Address *address, const struct GNUNET_ATS_Properties *prop) { struct GNUNET_ATS_AddressRecord *ar; struct AddressInfo *ai; if (0 == memcmp (&GST_my_identity, &address->peer, sizeof (struct GNUNET_PeerIdentity))) return; /* our own, ignore! */ /* validadte address */ if (NULL == address->transport_name) { GNUNET_break(0); return; } GNUNET_assert (GNUNET_YES != GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)); ai = find_ai_no_session (address); GNUNET_assert (NULL == ai); GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != prop->scope); /* address seems sane, let's tell ATS */ LOG (GNUNET_ERROR_TYPE_INFO, "Notifying ATS about peer %s's new address `%s'\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); ar = GNUNET_ATS_address_add (GST_ats, address, NULL, prop); GNUNET_assert (NULL != ar); ai = GNUNET_new (struct AddressInfo); ai->address = GNUNET_HELLO_address_copy (address); ai->ar = ar; ai->properties = *prop; (void) GNUNET_CONTAINER_multipeermap_put (p2a, &ai->address->peer, ai, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); publish_p2a_stat_update (); }
/** * 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; }
/** * Insert peer into the view * * @param peer the peer to insert * * @return GNUNET_OK if peer was actually inserted * GNUNET_NO if peer was not inserted */ int View_put (const struct GNUNET_PeerIdentity *peer) { uint32_t *index; if ((length <= View_size ()) || /* If array is 'full' */ (GNUNET_YES == View_contains_peer (peer))) { return GNUNET_NO; } else { index = GNUNET_new (uint32_t); *index = (uint32_t) View_size (); array[*index] = *peer; GNUNET_CONTAINER_multipeermap_put (mpm, peer, index, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); return GNUNET_OK; } }
/** * Signature of a function called by ATS with the current bandwidth * and address preferences as determined by ATS. * * @param cls closure, should point to "asc-closure" * @param peer for which we suggest an address, NULL if ATS connection died * @param address suggested address (including peer identity of the peer), * may be NULL to signal disconnect from peer * @param session session to use, NULL to establish a new outgoing session * @param bandwidth_out assigned outbound bandwidth for the connection, * 0 to signal disconnect * @param bandwidth_in assigned inbound bandwidth for the connection, * 0 to signal disconnect */ static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { const char *asc_cls = cls; struct AddressSuggestData *asd; GNUNET_break (0 == strcmp (asc_cls, "asc-closure")); if (NULL == peer) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to ATS died, likely a crash!\n"); GNUNET_SCHEDULER_shutdown (); #if 0 /* This is what we should do if we wanted to continue past the ATS crash. */ GNUNET_CONTAINER_multipeermap_iterate (p2asd, &free_asd, NULL); GNUNET_CONTAINER_multipeermap_iterate (p2aid, &free_aid, NULL); #endif return; } asd = find_address_suggestion (peer); if (NULL == asd) { asd = GNUNET_new (struct AddressSuggestData); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (p2asd, peer, asd, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); }
/** * Function called by transport to notify us that * a peer connected to us (on the network level). * * @param cls closure * @param peer the peer that connected */ static void handle_transport_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Neighbour *n; if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return; } n = find_neighbour (peer); if (NULL != n) { /* duplicate connect notification!? */ GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer %s exists already\n", GNUNET_i2s (peer)); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received connection from `%s'.\n", GNUNET_i2s (peer)); n = GNUNET_new (struct Neighbour); n->peer = *peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (neighbours, &n->peer, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"), GNUNET_CONTAINER_multipeermap_size (neighbours), GNUNET_NO); n->kxinfo = GSC_KX_start (peer); }
/** * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RequestAddressMessage *msg = (const struct RequestAddressMessage *) message; struct ConnectionRequest *cr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS"); /* FIXME: should not ignore "msg->strength" */ cr = GNUNET_new (struct ConnectionRequest); cr->client = client; (void) GNUNET_CONTAINER_multipeermap_put (connection_requests, &msg->peer, cr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GAS_plugin_request_connect_start (&msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Method called whenever a peer connects. Sets up the PeerEntry and * schedules the initial size info transmission to this peer. * * @param cls closure * @param peer peer identity this notification is about */ static void * handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq) { struct NSEPeerEntry *peer_entry; uint64_t flags; const void *extra; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", GNUNET_i2s (peer)); /* set our default transmission options */ extra = GNUNET_CORE_get_mq_options (GNUNET_NO, NSE_PRIORITY, &flags); GNUNET_MQ_set_options (mq, flags, extra); /* create our peer entry for this peer */ peer_entry = GNUNET_new (struct NSEPeerEntry); peer_entry->id = peer; peer_entry->mq = mq; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, peer_entry->id, peer_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb, peer_entry); GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); return peer_entry; }
/** * Create a new entry in the peer list. * * @param peer identity of the new entry * @param hello hello message, can be NULL * @param is_friend is the new entry for a friend? * @return the new entry */ static struct Peer * make_peer (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, int is_friend) { struct Peer *ret; ret = GNUNET_new (struct Peer); ret->pid = *peer; ret->is_friend = is_friend; if (NULL != hello) { ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello)); GNUNET_memcpy (ret->hello, hello, GNUNET_HELLO_size (hello)); } GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, peer, ret, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return ret; }
/** * Handles a message sent from the DV service to us. * Parse it out and give it to the plugin. * * @param cls the handle to the DV API * @param msg the message that was received */ static void handle_message_receipt (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DV_ServiceHandle *sh = cls; const struct GNUNET_DV_ConnectMessage *cm; const struct GNUNET_DV_DistanceUpdateMessage *dum; const struct GNUNET_DV_DisconnectMessage *dm; const struct GNUNET_DV_ReceivedMessage *rm; const struct GNUNET_MessageHeader *payload; const struct GNUNET_DV_AckMessage *ack; struct GNUNET_DV_TransmitHandle *th; struct GNUNET_DV_TransmitHandle *tn; struct ConnectedPeer *peer; if (NULL == msg) { /* Connection closed */ reconnect (sh); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u with %u bytes from DV service\n", (unsigned int) ntohs (msg->type), (unsigned int) ntohs (msg->size)); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_DV_CONNECT: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ConnectMessage)) { GNUNET_break (0); reconnect (sh); return; } cm = (const struct GNUNET_DV_ConnectMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &cm->peer); if (NULL != peer) { GNUNET_break (0); reconnect (sh); return; } peer = GNUNET_new (struct ConnectedPeer); peer->pid = cm->peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (sh->peers, &peer->pid, peer, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); sh->connect_cb (sh->cls, &cm->peer, ntohl (cm->distance), (enum GNUNET_ATS_Network_Type) ntohl (cm->network)); break; case GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DistanceUpdateMessage)) { GNUNET_break (0); reconnect (sh); return; } dum = (const struct GNUNET_DV_DistanceUpdateMessage *) msg; sh->distance_cb (sh->cls, &dum->peer, ntohl (dum->distance), (enum GNUNET_ATS_Network_Type) ntohl (dum->network)); break; case GNUNET_MESSAGE_TYPE_DV_DISCONNECT: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DisconnectMessage)) { GNUNET_break (0); reconnect (sh); return; } dm = (const struct GNUNET_DV_DisconnectMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &dm->peer); if (NULL == peer) { GNUNET_break (0); reconnect (sh); return; } tn = sh->th_head; while (NULL != (th = tn)) { tn = th->next; if (peer == th->target) { GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, th); th->cb (th->cb_cls, GNUNET_SYSERR); GNUNET_free (th); } } cleanup_send_cb (sh, &dm->peer, peer); break; case GNUNET_MESSAGE_TYPE_DV_RECV: if (ntohs (msg->size) < sizeof (struct GNUNET_DV_ReceivedMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); reconnect (sh); return; } rm = (const struct GNUNET_DV_ReceivedMessage *) msg; payload = (const struct GNUNET_MessageHeader *) &rm[1]; if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (payload->size)) { GNUNET_break (0); reconnect (sh); return; } if (NULL == GNUNET_CONTAINER_multipeermap_get (sh->peers, &rm->sender)) { GNUNET_break (0); reconnect (sh); return; } sh->message_cb (sh->cls, &rm->sender, ntohl (rm->distance), payload); break; case GNUNET_MESSAGE_TYPE_DV_SEND_ACK: case GNUNET_MESSAGE_TYPE_DV_SEND_NACK: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_AckMessage)) { GNUNET_break (0); reconnect (sh); return; } ack = (const struct GNUNET_DV_AckMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &ack->target); if (NULL == peer) break; /* this happens, just ignore */ for (th = peer->head; NULL != th; th = th->next) { if (th->uid != ntohl (ack->uid)) continue; LOG (GNUNET_ERROR_TYPE_DEBUG, "Matched ACK for message to peer %s\n", GNUNET_i2s (&ack->target)); GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, th); th->cb (th->cb_cls, (ntohs (ack->header.type) == GNUNET_MESSAGE_TYPE_DV_SEND_ACK) ? GNUNET_OK : GNUNET_SYSERR); GNUNET_free (th); break; } break; default: reconnect (sh); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message, continuing receive loop for %p\n", sh->client); GNUNET_CLIENT_receive (sh->client, &handle_message_receipt, sh, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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; }
/** * Handler for notification messages received from the core. * * @param cls our `struct GNUNET_CORE_Handle` * @param msg the message received from the core service */ static void main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CORE_Handle *h = cls; const struct InitReplyMessage *m; const struct ConnectNotifyMessage *cnm; const struct DisconnectNotifyMessage *dnm; const struct NotifyTrafficMessage *ntm; const struct GNUNET_MessageHeader *em; const struct SendMessageReady *smr; const struct GNUNET_CORE_MessageHandler *mh; GNUNET_CORE_StartupCallback init; struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; unsigned int hpos; int trigger; uint16_t msize; uint16_t et; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_INFO, _("Client was disconnected from core service, trying to reconnect.\n")); reconnect_later (h); return; } msize = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing message of type %u and size %u from core service\n", ntohs (msg->type), msize); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY: if (ntohs (msg->size) != sizeof (struct InitReplyMessage)) { GNUNET_break (0); reconnect_later (h); return; } m = (const struct InitReplyMessage *) msg; GNUNET_break (0 == ntohl (m->reserved)); /* start our message processing loop */ if (GNUNET_YES == h->currently_down) { h->currently_down = GNUNET_NO; trigger_next_request (h, GNUNET_NO); } h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS; h->me = m->my_identity; if (NULL != (init = h->init)) { /* mark so we don't call init on reconnect */ h->init = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to core service of peer `%s'.\n", GNUNET_i2s (&h->me)); init (h->cls, &h->me); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully reconnected to core service.\n"); } /* fake 'connect to self' */ pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &h->me); GNUNET_assert (NULL == pr); pr = GNUNET_new (struct PeerRecord); pr->peer = h->me; pr->ch = h; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (h->peers, &h->me, pr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); if (NULL != h->connects) h->connects (h->cls, &h->me); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: if (msize < sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } cnm = (const struct ConnectNotifyMessage *) msg; if (msize != sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about connection from `%s'.\n", GNUNET_i2s (&cnm->peer)); if (0 == memcmp (&h->me, &cnm->peer, sizeof (struct GNUNET_PeerIdentity))) { /* connect to self!? */ GNUNET_break (0); return; } pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer); if (NULL != pr) { GNUNET_break (0); reconnect_later (h); return; } pr = GNUNET_new (struct PeerRecord); pr->peer = cnm->peer; pr->ch = h; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (h->peers, &cnm->peer, pr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); if (NULL != h->connects) h->connects (h->cls, &cnm->peer); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT: if (msize != sizeof (struct DisconnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } dnm = (const struct DisconnectNotifyMessage *) msg; if (0 == memcmp (&h->me, &dnm->peer, sizeof (struct GNUNET_PeerIdentity))) { /* connection to self!? */ GNUNET_break (0); return; } GNUNET_break (0 == ntohl (dnm->reserved)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about disconnect from `%s'.\n", GNUNET_i2s (&dnm->peer)); pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } trigger = ((pr->prev != NULL) || (pr->next != NULL) || (h->ready_peer_head == pr)); disconnect_and_free_peer_entry (h, &dnm->peer, pr); if (trigger) trigger_next_request (h, GNUNET_NO); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND: if (msize < sizeof (struct NotifyTrafficMessage)) { GNUNET_break (0); reconnect_later (h); return; } ntm = (const struct NotifyTrafficMessage *) msg; if ((msize < sizeof (struct NotifyTrafficMessage) + sizeof (struct GNUNET_MessageHeader)) ) { GNUNET_break (0); reconnect_later (h); return; } em = (const struct GNUNET_MessageHeader *) &ntm[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u and size %u from peer `%4s'\n", ntohs (em->type), ntohs (em->size), GNUNET_i2s (&ntm->peer)); if ((GNUNET_NO == h->inbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { GNUNET_break (0); reconnect_later (h); return; } et = ntohs (em->type); for (hpos = 0; hpos < h->hcnt; hpos++) { mh = &h->handlers[hpos]; if (mh->type != et) continue; if ((mh->expected_size != ntohs (em->size)) && (mh->expected_size != 0)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Unexpected message size %u for message of type %u from peer `%4s'\n", htons (em->size), mh->type, GNUNET_i2s (&ntm->peer)); GNUNET_break_op (0); continue; } pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } if (GNUNET_OK != h->handlers[hpos].callback (h->cls, &ntm->peer, em)) { /* error in processing, do not process other messages! */ break; } } if (NULL != h->inbound_notify) h->inbound_notify (h->cls, &ntm->peer, em); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND: if (msize < sizeof (struct NotifyTrafficMessage)) { GNUNET_break (0); reconnect_later (h); return; } ntm = (const struct NotifyTrafficMessage *) msg; if ((msize < sizeof (struct NotifyTrafficMessage) + sizeof (struct GNUNET_MessageHeader)) ) { GNUNET_break (0); reconnect_later (h); return; } em = (const struct GNUNET_MessageHeader *) &ntm[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about transmission to `%s'.\n", GNUNET_i2s (&ntm->peer)); if ((GNUNET_NO == h->outbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { GNUNET_break (0); reconnect_later (h); return; } if (NULL == h->outbound_notify) { GNUNET_break (0); break; } h->outbound_notify (h->cls, &ntm->peer, em); break; case GNUNET_MESSAGE_TYPE_CORE_SEND_READY: if (msize != sizeof (struct SendMessageReady)) { GNUNET_break (0); reconnect_later (h); return; } smr = (const struct SendMessageReady *) msg; pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about transmission readiness to `%s'.\n", GNUNET_i2s (&smr->peer)); if (NULL == pr->th.peer) { /* request must have been cancelled between the original request * and the response from core, ignore core's readiness */ break; } th = &pr->th; if (ntohs (smr->smr_id) != th->smr_id) { /* READY message is for expired or cancelled message, * ignore! (we should have already sent another request) */ break; } if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr)) { /* we should not already be on the ready list... */ GNUNET_break (0); reconnect_later (h); return; } GNUNET_CONTAINER_DLL_insert (h->ready_peer_head, h->ready_peer_tail, pr); trigger_next_request (h, GNUNET_NO); break; default: reconnect_later (h); return; } GNUNET_CLIENT_receive (h->client, &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *dbfile; struct WhiteListRow *wl_head; struct WhiteListRow *wl_entry; struct GNUNET_PeerIdentity identity; struct GNUNET_ATS_Properties prop; struct GNUNET_TIME_Relative delay; unsigned long long pid; unsigned int nrows; int ret; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "TESTBED", "PEERID", &pid)) { GNUNET_break (0); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED-UNDERLAY", "DBFILE", &dbfile)) { GNUNET_break (0); return; } if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL))) { if (NULL != db) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); GNUNET_break (SQLITE_OK == sqlite3_close (db)); } else LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); GNUNET_free (dbfile); return; } DEBUG ("Opened database %s\n", dbfile); GNUNET_free (dbfile); dbfile = NULL; wl_head = NULL; if (GNUNET_OK != load_keys (c)) goto close_db; transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL); if (NULL == transport) { GNUNET_break (0); return; } /* read and process whitelist */ nrows = 0; wl_head = NULL; nrows = db_read_whitelist (db, pid, &wl_head); if ((GNUNET_SYSERR == nrows) || (0 == nrows)) { GNUNET_TRANSPORT_disconnect (transport); goto close_db; } map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO); while (NULL != (wl_entry = wl_head)) { wl_head = wl_entry->next; delay.rel_value_us = wl_entry->latency; memset (&prop, 0, sizeof (prop)); GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity)); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); DEBUG ("Setting %u ms latency to peer `%s'\n", wl_entry->latency, GNUNET_i2s (&identity)); GNUNET_TRANSPORT_set_traffic_metric (transport, &identity, &prop, delay, delay); GNUNET_free (wl_entry); } bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); close_db: GNUNET_break (SQLITE_OK == sqlite3_close (db)); return; }
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 #GNUNET_MESSAGE_TYPE_CORE_INIT request. * * @param cls unused * @param client new client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT * @param message the `struct InitMessage` (presumably) */ static void handle_client_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct InitMessage *im; struct InitReplyMessage irm; struct GSC_Client *c; uint16_t msize; const uint16_t *types; uint16_t *wtypes; unsigned int i; /* check that we don't have an entry already */ c = find_client (client); if (NULL != c) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize < sizeof (struct InitMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_notification_context_add (notifier, client); im = (const struct InitMessage *) message; types = (const uint16_t *) &im[1]; msize -= sizeof (struct InitMessage); c = GNUNET_malloc (sizeof (struct GSC_Client) + msize); c->client_handle = client; c->tcnt = msize / sizeof (uint16_t); c->options = ntohl (im->options); all_client_options |= c->options; c->types = (const uint16_t *) &c[1]; c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (c->connectmap, &GSC_my_identity, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); wtypes = (uint16_t *) & c[1]; for (i = 0; i < c->tcnt; i++) wtypes[i] = ntohs (types[i]); GSC_TYPEMAP_add (wtypes, c->tcnt); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connecting to core service is interested in %u message types\n", (unsigned int) c->tcnt); /* send init reply message */ irm.header.size = htons (sizeof (struct InitReplyMessage)); irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY); irm.reserved = htonl (0); irm.my_identity = GSC_my_identity; send_to_client (c, &irm.header, GNUNET_NO); GSC_SESSIONS_notify_client_about_sessions (c); GNUNET_SERVER_receive_done (client, GNUNET_OK); }