/** * Remove peer from view * * @param peer the peer to remove * * @return GNUNET_OK if view contained peer and removed it successfully * GNUNET_NO if view does not contain peer */ int View_remove_peer (const struct GNUNET_PeerIdentity *peer) { uint32_t *index; uint32_t *swap_index; uint32_t last_index; if (GNUNET_NO == View_contains_peer (peer)) { return GNUNET_NO; } index = GNUNET_CONTAINER_multipeermap_get (mpm, peer); GNUNET_assert (NULL != index); last_index = View_size () - 1; if (*index < last_index) { /* Fill the 'gap' in the array with the last peer */ array[*index] = array[last_index]; GNUNET_assert (GNUNET_YES == View_contains_peer (&array[last_index])); swap_index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[last_index]); GNUNET_assert (NULL != swap_index); *swap_index = *index; GNUNET_free (index); } GNUNET_CONTAINER_multipeermap_remove_all (mpm, peer); return GNUNET_OK; }
struct Node * get_node (const struct GNUNET_PeerIdentity *id) { struct Node * res; struct Node * tmp; res = NULL; tmp = NULL; tmp = GNUNET_CONTAINER_multipeermap_get (nodes_active, id); if (res == NULL) res = tmp; tmp = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, id); if (res == NULL) res = tmp; else GNUNET_break (0); /* Multiple instances */ tmp = GNUNET_CONTAINER_multipeermap_get (nodes_requested, id); if (res == NULL) res = tmp; else GNUNET_break (0); /* Multiple instances */ return res; }
/** * PEERINFO calls this function to let us know about a possible peer * that we might want to connect to. * * @param cls closure (not used) * @param peer potential peer to connect to * @param hello HELLO for this peer (or NULL) * @param err_msg NULL if successful, otherwise contains error message */ static void process_peer (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct Peer *pos; if (NULL != err_msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Error in communication with PEERINFO service: %s\n"), err_msg); GNUNET_PEERINFO_notify_cancel (peerinfo_notify); peerinfo_notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); return; } GNUNET_assert (NULL != peer); if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* that's me! */ if (NULL == hello) { /* free existing HELLO, if any */ pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL != pos) { GNUNET_free_non_null (pos->hello); pos->hello = NULL; if (NULL != pos->filter) { GNUNET_CONTAINER_bloomfilter_free (pos->filter); pos->filter = NULL; } if ( (NULL == pos->mq) && (GNUNET_NO == pos->is_friend) ) free_peer (NULL, &pos->pid, pos); } return; } consider_for_advertising (hello); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) pos = make_peer (peer, hello, GNUNET_NO); attempt_connect (pos); }
/** * 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; }
/** * The owning peer of this path is no longer interested in maintaining * it, so the path should be discarded or shortened (in case a * previous peer on the path finds the path desirable). * * @param path the path that is being released */ void GCPP_release (struct CadetPeerPath *path) { struct CadetPeerPathEntry *entry; path->hn = NULL; entry = &path->entries[path->entries_length - 1]; while (1) { /* cut 'off' end of path, verifying it is not in use */ GNUNET_assert (NULL == GNUNET_CONTAINER_multipeermap_get (path->connections, GCP_get_id (entry->peer))); GCP_path_entry_remove (entry->peer, entry, path->entries_length - 1); path->entries_length--; /* We don't bother shrinking the 'entries' array, as it's probably not worth it. */ if (0 == path->entries_length) break; /* the end */ /* see if new peer at the end likes this path any better */ entry = &path->entries[path->entries_length - 1]; path->hn = GCP_attach_path (entry->peer, path, path->entries_length); if (NULL != path->hn) return; /* yep, got attached, we are done. */ } /* nobody wants us, discard the path */ path_destroy (path); }
/** * 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); }
/** * 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); }
/** * Intern an peer identity. If the identity is already known, its * reference counter will be increased by one. * * @param pid identity to intern * @return the interned identity. */ GNUNET_PEER_Id GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid) { GNUNET_PEER_Id ret; struct PeerEntry *e; unsigned int i; if (NULL == pid) return 0; if (NULL == map) map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES); e = GNUNET_CONTAINER_multipeermap_get (map, pid); if (NULL != e) { GNUNET_assert (e->rc > 0); e->rc++; return e->pid; } ret = free_list_start; if (ret == size) { GNUNET_array_grow (table, size, size + 16); for (i = ret; i < size; i++) { table[i] = GNUNET_new (struct PeerEntry); table[i]->pid = i + 1; } }
/** * Update the total releative preference for a peer by summing * up the relative preferences all clients have for this peer. * * @param id peer id of the peer for which we should do the update * @param kind the kind of preference value to update * @return the new relative preference */ static void update_relative_values_for_peer (const struct GNUNET_PeerIdentity *id, enum GNUNET_ATS_PreferenceKind kind) { struct PreferenceClient *c_cur; struct SumContext sum_ctx; struct PeerRelative *rp; sum_ctx.f_rel_total = 0.0; sum_ctx.kind = kind; for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) GNUNET_CONTAINER_multipeermap_get_multiple (c_cur->peer2pref, id, &sum_relative_preferences, &sum_ctx); LOG (GNUNET_ERROR_TYPE_DEBUG, "Total relative preference for peer `%s' for `%s' is %.3f\n", GNUNET_i2s (id), GNUNET_ATS_print_preference_type (kind), sum_ctx.f_rel_total); rp = GNUNET_CONTAINER_multipeermap_get (preference_peers, id); GNUNET_assert (NULL != rp); if (rp->f_rel[kind] != sum_ctx.f_rel_total) { rp->f_rel[kind] = sum_ctx.f_rel_total; GAS_plugin_notify_preference_changed (id, kind, rp->f_rel[kind]); } }
/** * 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); } }
/** * Find the entry for the given neighbour. * * @param peer identity of the neighbour * @return NULL if we are not connected, otherwise the * neighbour's entry. */ static struct Neighbour * find_neighbour (const struct GNUNET_PeerIdentity *peer) { if (NULL == neighbours) return NULL; return GNUNET_CONTAINER_multipeermap_get (neighbours, peer); }
/** * Method called whenever a peer connects. * * @param cls closure * @param peer peer identity this notification is about * @param mq message queue for communicating with @a peer * @return our `struct Peer` for @a peer */ static void * connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq) { struct Peer *pos; uint64_t flags; const void *extra; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core told us that we are connecting to `%s'\n", GNUNET_i2s (peer)); if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return NULL; extra = GNUNET_CORE_get_mq_options (GNUNET_YES, GNUNET_CORE_PRIO_BEST_EFFORT, &flags); GNUNET_MQ_set_options (mq, flags, extra); connection_count++; GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"), connection_count, GNUNET_NO); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) { pos = make_peer (peer, NULL, GNUNET_NO); } else { GNUNET_assert (NULL == pos->mq); } pos->mq = mq; if (pos->is_friend) { friend_count++; if ( (friend_count == minimum_friend_count) && (GNUNET_YES != friends_only) ) whitelist_peers (); GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"), friend_count, GNUNET_NO); } reschedule_hellos (NULL, peer, pos); return pos; }
/** * Ask the core to call @a notify once it is ready to transmit the * given number of bytes to the specified @a target. Must only be * called after a connection to the respective peer has been * established (and the client has been informed about this). You may * have one request of this type pending for each connected peer at * any time. If a peer disconnects, the application MUST call * #GNUNET_CORE_notify_transmit_ready_cancel on the respective * transmission request, if one such request is pending. * * @param handle connection to core service * @param cork is corking allowed for this transmission? * @param priority how important is the message? * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES * @param target who should receive the message, never NULL (can be this peer's identity for loopback) * @param notify_size how many bytes of buffer space does @a notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout; clients MUST cancel * all pending transmission requests DURING the disconnect * handler * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we can not even queue the request (request already pending); * if NULL is returned, @a notify will NOT be called. */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, int cork, enum GNUNET_CORE_Priority priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; if (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } GNUNET_assert (NULL != notify); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asking core for transmission of %u bytes to `%s'\n", (unsigned int) notify_size, GNUNET_i2s (target)); pr = GNUNET_CONTAINER_multipeermap_get (handle->peers, target); if (NULL == pr) { /* attempt to send to peer that is not connected */ GNUNET_break (0); return NULL; } if (NULL != pr->th.peer) { /* attempting to queue a second request for the same destination */ GNUNET_break (0); return NULL; } GNUNET_assert (notify_size + sizeof (struct SendMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); th = &pr->th; memset (th, 0, sizeof (struct GNUNET_CORE_TransmitHandle)); th->peer = pr; th->get_message = notify; th->get_message_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->priority = priority; th->msize = notify_size; th->cork = cork; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_add_now (&run_request_next_transmission, pr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission request added to queue\n"); return th; }
/** * Send a message via DV service. * * @param sh service handle * @param target intended recpient * @param msg message payload * @param cb function to invoke when done * @param cb_cls closure for @a cb * @return handle to cancel the operation */ struct GNUNET_DV_TransmitHandle * GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, GNUNET_DV_MessageSentCallback cb, void *cb_cls) { struct GNUNET_DV_TransmitHandle *th; struct GNUNET_DV_SendMessage *sm; struct ConnectedPeer *peer; if (ntohs (msg->size) + sizeof (struct GNUNET_DV_SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to send %u bytes of type %u to %s via %p\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type), GNUNET_i2s (target), sh->client); peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, target); if (NULL == peer) { GNUNET_break (0); return NULL; } th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) + sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); th->sh = sh; th->target = peer; th->cb = cb; th->cb_cls = cb_cls; th->msg = (const struct GNUNET_MessageHeader *) &th[1]; sm = (struct GNUNET_DV_SendMessage *) &th[1]; sm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND); sm->header.size = htons (sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); if (0 == sh->uid_gen) sh->uid_gen = 1; th->uid = sh->uid_gen; sm->uid = htonl (sh->uid_gen++); /* use memcpy here as 'target' may not be sufficiently aligned */ memcpy (&sm->target, target, sizeof (struct GNUNET_PeerIdentity)); memcpy (&sm[1], msg, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (sh->th_head, sh->th_tail, th); start_transmit (sh); return th; }
/** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity * peer) { struct Node *n; if (GNUNET_YES == is_me(peer)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Disconnected from peer %s\n"), GNUNET_i2s (peer)); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) cleanup_node (nodes_requested, peer, n); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) cleanup_node (nodes_active, peer, n); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) cleanup_node (nodes_inactive, peer, n); }
/** * Find the next hop to send packet to . * @return next hop peer id */ struct GNUNET_PeerIdentity * GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *destination_peer) { struct RoutingTrail *trail; trail = (struct RoutingTrail *)(GNUNET_CONTAINER_multipeermap_get(routing_table,destination_peer)); if(trail == NULL) return NULL; return trail->next_hop; }
/** * @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; }
/** * 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; }
/** * Search for a peer identity. The reference counter is not changed. * * @param pid identity to find * @return the interned identity or 0. */ GNUNET_PEER_Id GNUNET_PEER_search (const struct GNUNET_PeerIdentity *pid) { struct PeerEntry *e; if (NULL == pid) return 0; if (NULL == map) return 0; e = GNUNET_CONTAINER_multipeermap_get (map, pid); if (NULL == e) return 0; GNUNET_assert (e->rc > 0); return e->pid; }
/** * 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 ()); }
/** * Function that decides if a connection is acceptable or not. * If we have a blacklist, only friends are allowed, so the check * is rather simple. * * @param cls closure * @param pid peer to approve or disapprove * @return #GNUNET_OK if the connection is allowed */ static int blacklist_check (void *cls, const struct GNUNET_PeerIdentity *pid) { struct Peer *pos; pos = GNUNET_CONTAINER_multipeermap_get (peers, pid); if ( (NULL != pos) && (GNUNET_YES == pos->is_friend)) return GNUNET_OK; GNUNET_STATISTICS_update (stats, gettext_noop ("# peers blacklisted"), 1, GNUNET_NO); return GNUNET_SYSERR; }
/** * Calculate ECC discrete logarithm for small factors. * * @param edc precalculated values, determine range of factors * @param input point on the curve to factor * @return `edc->max` if dlog failed, otherwise the factor */ int GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, gcry_mpi_point_t input) { unsigned int K = ((edc->max + (edc->mem-1)) / edc->mem); gcry_mpi_point_t g; struct GNUNET_PeerIdentity key; gcry_mpi_point_t q; unsigned int i; int res; void *retp; g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); q = gcry_mpi_point_new (0); res = edc->max; for (i=0;i<=edc->max/edc->mem;i++) { if (0 == i) extract_pk (input, edc->ctx, &key); else extract_pk (q, edc->ctx, &key); retp = GNUNET_CONTAINER_multipeermap_get (edc->map, &key); if (NULL != retp) { res = (((long) retp) - edc->max) * K - i; /* we continue the loop here to make the implementation "constant-time". If we do not care about this, we could just 'break' here and do fewer operations... */ } if (i == edc->max/edc->mem) break; /* q = q + g */ if (0 == i) gcry_mpi_ec_add (q, input, g, edc->ctx); else gcry_mpi_ec_add (q, q, g, edc->ctx); } gcry_mpi_point_release (g); gcry_mpi_point_release (q); return res; }
/** * 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); }
/** * This function is called whenever an encrypted HELLO message is * received. * * @param cls closure with the peer identity of the sender * @param message the actual HELLO message */ static void handle_hello (void *cls, const struct GNUNET_HELLO_Message *message) { const struct GNUNET_PeerIdentity *other = cls; struct Peer *peer; struct GNUNET_PeerIdentity pid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received encrypted HELLO from peer `%s'", GNUNET_i2s (other)); GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (message, &pid)); GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages received"), 1, GNUNET_NO); peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); if (NULL == peer) { if ( (GNUNET_YES == friends_only) || (friend_count < minimum_friend_count) ) return; } else { if ( (GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only) ) return; if ((GNUNET_YES != peer->is_friend) && (friend_count < minimum_friend_count)) return; } if (NULL != oh) GNUNET_TRANSPORT_offer_hello_cancel (oh); oh = GNUNET_TRANSPORT_offer_hello (cfg, &message->header, &done_offer_hello, NULL); }
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); }
/** * 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); }
/** * 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); }
/** * Find the session for the given peer. * * @param peer identity of the peer * @return NULL if we are not connected, otherwise the * session handle */ static struct Session * find_session (const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_get (sessions, peer); }
/** * 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); }