/** * 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); }
/** * Client is done with ATS scheduling, release resources. * * @param sh handle to release */ void GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh) { struct GNUNET_ATS_AddressRecord *ar; unsigned int i; if (NULL != sh->mq) { GNUNET_MQ_destroy (sh->mq); sh->mq = NULL; } if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } if (NULL != sh->task) { GNUNET_SCHEDULER_cancel (sh->task); sh->task = NULL; } for (i=0;i<sh->session_array_size;i++) { if (NULL != (ar = sh->session_array[i])) { GNUNET_HELLO_address_free (ar->address); GNUNET_free (ar); sh->session_array[i] = NULL; } } GNUNET_array_grow (sh->session_array, sh->session_array_size, 0); GNUNET_free (sh); }
/** * Create a host to run peers and controllers on. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @param hostname name of the host, use "NULL" for localhost * @param username username to use for the login; may be NULL * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @param port port number to use for ssh; use 0 to let ssh decide * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname, const char *username, const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t port) { struct GNUNET_TESTBED_Host *host; unsigned int new_size; if ((id < host_list_size) && (NULL != host_list[id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id); return NULL; } host = GNUNET_new (struct GNUNET_TESTBED_Host); host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL; host->username = (NULL != username) ? GNUNET_strdup (username) : NULL; host->id = id; host->port = (0 == port) ? 22 : port; host->cfg = GNUNET_CONFIGURATION_dup (cfg); host->opq_parallel_overlay_connect_operations = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE, UINT_MAX); new_size = host_list_size; while (id >= new_size) new_size += HOST_LIST_GROW_STEP; if (new_size != host_list_size) GNUNET_array_grow (host_list, host_list_size, new_size); GNUNET_assert (id < host_list_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding host with id: %u\n", host->id); host_list[id] = host; return host; }
/** * 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; } }
/** * Delete the given value, removing it from the plugin's data * structures. * * @param plugin the plugin * @param value value to delete */ static void delete_value (struct Plugin *plugin, struct Value *value) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->keyvalue, &value->key, value)); GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->expire_heap)); GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->replication_heap)); if (0 == value->anonymity) { struct ZeroAnonByType *zabt; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) if (zabt->type == value->type) break; GNUNET_assert (NULL != zabt); zabt->array[value->zero_anon_offset] = zabt->array[--zabt->array_pos]; zabt->array[value->zero_anon_offset]->zero_anon_offset = value->zero_anon_offset; if (0 == zabt->array_pos) { GNUNET_array_grow (zabt->array, zabt->array_size, 0); GNUNET_CONTAINER_DLL_remove (plugin->zero_head, plugin->zero_tail, zabt); GNUNET_free (zabt); } } plugin->size -= value->size; GNUNET_free (value); }
/** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; struct Value *value; value = GNUNET_malloc (sizeof (struct Value) + size); value->key = *key; value->data = &value[1]; value->expire_heap = GNUNET_CONTAINER_heap_insert (plugin->by_expiration, value, expiration.abs_value); value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication, value, replication); value->expiration = expiration; if (0 == anonymity) { struct ZeroAnonByType *zabt; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) if (zabt->type == type) break; if (NULL == zabt) { zabt = GNUNET_malloc (sizeof (struct ZeroAnonByType)); zabt->type = type; GNUNET_CONTAINER_DLL_insert (plugin->zero_head, plugin->zero_tail, zabt); } if (zabt->array_size == zabt->array_pos) { GNUNET_array_grow (zabt->array, zabt->array_size, zabt->array_size * 2 + 4); } value->zero_anon_offset = zabt->array_pos; zabt->array[zabt->array_pos++] = value; } value->size = size; value->priority = priority; value->anonymity = anonymity; value->replication = replication; value->type = type; memcpy (&value[1], data, size); GNUNET_CONTAINER_multihashmap_put (plugin->keyvalue, &value->key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); plugin->size += size; return GNUNET_OK; }
/** * @brief Set the peer flag to living and * call the pending operations on this peer. * * Also adds peer to #valid_peers. * * @param peer_ctx the #PeerContext of the peer to set live */ static void set_peer_live (struct PeerContext *peer_ctx) { struct GNUNET_PeerIdentity *peer; unsigned int i; peer = &peer_ctx->peer_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is live and valid, calling %i pending operations on it\n", GNUNET_i2s (peer), peer_ctx->num_pending_ops); if (NULL != peer_ctx->liveliness_check_pending) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing pending liveliness check for peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); // TODO wait until cadet sets mq->cancel_impl //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev); GNUNET_free (peer_ctx->liveliness_check_pending); peer_ctx->liveliness_check_pending = NULL; } (void) add_valid_peer (peer); set_peer_flag (peer_ctx, Peers_ONLINE); /* Call pending operations */ for (i = 0; i < peer_ctx->num_pending_ops; i++) { peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer); } GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); }
/** * Destroy connection with the service. This will automatically * cancel any pending "receive" request (however, the handler will * *NOT* be called, not even with a NULL message). Any pending * transmission request will also be cancelled UNLESS the callback for * the transmission request has already been called, in which case the * transmission 'finish_pending_write' argument determines whether or * not the write is guaranteed to complete before the socket is fully * destroyed (unless, of course, there is an error with the server in * which case the message may still be lost). * * @param client handle to the service connection */ void GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client) { if (GNUNET_YES == client->in_receive) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; } if (NULL != client->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (client->th); client->th = NULL; } if (NULL != client->connection) { GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; } if (GNUNET_SCHEDULER_NO_TASK != client->receive_task) { GNUNET_SCHEDULER_cancel (client->receive_task); client->receive_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != client->tag) { GNUNET_free (client->tag); client->tag = NULL; } client->receiver_handler = NULL; GNUNET_array_grow (client->received_buf, client->received_size, 0); GNUNET_free (client->service_name); GNUNET_free (client); }
/** * Destructor that frees the KSK cache. */ void __attribute__ ((destructor)) GNUNET_CRYPTO_ksk_fini () { unsigned int i; for (i = 0; i < cacheSize; i++) { GNUNET_free (cache[i]->pke); GNUNET_free (cache[i]); } GNUNET_array_grow (cache, cacheSize, 0); }
/** * Callback function for data received from the network. Note that * both "available" and "errCode" would be 0 if the read simply timed out. * * @param cls closure * @param buf pointer to received data * @param available number of bytes availabe in "buf", * possibly 0 (on errors) * @param addr address of the sender * @param addrlen size of addr * @param errCode value of errno (on errors receiving) */ static void receive_helper (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { struct GNUNET_CLIENT_Connection *client = cls; struct GNUNET_TIME_Relative remaining; GNUNET_CLIENT_MessageHandler receive_handler; void *receive_handler_cls; GNUNET_assert (GNUNET_NO == client->msg_complete); GNUNET_assert (GNUNET_YES == client->in_receive); client->in_receive = GNUNET_NO; if ((0 == available) || (NULL == client->connection) || (0 != errCode)) { /* signal timeout! */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n", (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL", STRERROR (errCode)); if (NULL != (receive_handler = client->receiver_handler)) { receive_handler_cls = client->receiver_handler_cls; client->receiver_handler = NULL; receive_handler (receive_handler_cls, NULL); } return; } /* FIXME: optimize for common fast case where buf contains the * entire message and we need no copying... */ /* slow path: append to array */ if (client->received_size < client->received_pos + available) GNUNET_array_grow (client->received_buf, client->received_size, client->received_pos + available); memcpy (&client->received_buf[client->received_pos], buf, available); client->received_pos += available; check_complete (client); /* check for timeout */ remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout); if (0 == remaining.rel_value) { /* signal timeout! */ if (NULL != client->receiver_handler) client->receiver_handler (client->receiver_handler_cls, NULL); return; } /* back to receive -- either for more data or to call callback! */ GNUNET_CLIENT_receive (client, client->receiver_handler, client->receiver_handler_cls, remaining); }
/** * Stop async DHT-get. * * @param get_handle handle to the GET operation to stop */ void GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle) { struct GNUNET_DHT_Handle *handle; const struct GNUNET_DHT_ClientGetMessage *get_msg; struct GNUNET_DHT_ClientGetStopMessage *stop_msg; struct PendingMessage *pending; handle = get_handle->message->handle; get_msg = (const struct GNUNET_DHT_ClientGetMessage *) get_handle->message->msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending STOP for %s to DHT via %p\n", GNUNET_h2s (&get_msg->key), handle); /* generate STOP */ pending = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg = (struct GNUNET_DHT_ClientGetStopMessage *) &pending[1]; pending->msg = &stop_msg->header; pending->handle = handle; pending->free_on_send = GNUNET_YES; stop_msg->header.size = htons (sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP); stop_msg->reserved = htonl (0); stop_msg->unique_id = get_msg->unique_id; stop_msg->key = get_msg->key; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; /* remove 'GET' from active status */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->active_requests, &get_handle->key, get_handle)); if (GNUNET_YES == get_handle->message->in_pending_queue) { GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, get_handle->message); get_handle->message->in_pending_queue = GNUNET_NO; } GNUNET_free (get_handle->message); GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_end, 0); GNUNET_free (get_handle); process_pending_messages (handle); }
/** * Handler for "GET result seen" messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetResultSeenMessage *seen; uint16_t size; unsigned int hash_count; unsigned int old_count; const struct GNUNET_HashCode *hc; struct FindByUniqueIdContext fui_ctx; struct ClientQueryRecord *cqr; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message; hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode); if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } hc = (const struct GNUNET_HashCode*) &seen[1]; fui_ctx.unique_id = seen->unique_id; fui_ctx.cqr = NULL; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &seen->key, &find_by_unique_id, &fui_ctx); if (NULL == (cqr = fui_ctx.cqr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* finally, update 'seen' list */ old_count = cqr->seen_replies_count; GNUNET_array_grow (cqr->seen_replies, cqr->seen_replies_count, cqr->seen_replies_count + hash_count); memcpy (&cqr->seen_replies[old_count], hc, sizeof (struct GNUNET_HashCode) * hash_count); }
/** * Initialize the ATS subsystem. * * @param cfg configuration to use * @param suggest_cb notification to call whenever the suggestation changed * @param suggest_cb_cls closure for @a suggest_cb * @return ats context */ struct GNUNET_ATS_SchedulingHandle * GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_AddressSuggestionCallback suggest_cb, void *suggest_cb_cls) { struct GNUNET_ATS_SchedulingHandle *sh; sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle); sh->cfg = cfg; sh->suggest_cb = suggest_cb; sh->suggest_cb_cls = suggest_cb_cls; GNUNET_array_grow (sh->session_array, sh->session_array_size, 4); reconnect (sh); return sh; }
/** * Deterministically (!) create a hostkey using only the * given HashCode as input to the PRNG. * * @param hc hash code to generate the key from * @return corresponding private key; must not be freed! */ struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode * hc) { struct KBlockKeyCacheLine *line; unsigned int i; for (i = 0; i < cacheSize; i++) if (0 == memcmp (hc, &cache[i]->hc, sizeof (struct GNUNET_HashCode))) return GNUNET_CRYPTO_rsa_decode_key ((const char*) cache[i]->pke, ntohs (cache[i]->pke->len)); line = GNUNET_malloc (sizeof (struct KBlockKeyCacheLine)); line->hc = *hc; line->pke = makeKblockKeyInternal (hc); GNUNET_array_grow (cache, cacheSize, cacheSize + 1); cache[cacheSize - 1] = line; return GNUNET_CRYPTO_rsa_decode_key ((const char*) line->pke, ntohs (line->pke->len)); }
/** * Tell the DHT not to return any of the following known results * to this client. * * @param get_handle get operation for which results should be filtered * @param num_results number of results to be blocked that are * provided in this call (size of the @a results array) * @param results array of hash codes over the 'data' of the results * to be blocked */ void GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle, unsigned int num_results, const struct GNUNET_HashCode *results) { unsigned int needed; needed = get_handle->seen_results_end + num_results; if (needed > get_handle->seen_results_size) GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_size, needed); memcpy (&get_handle->seen_results[get_handle->seen_results_end], results, num_results * sizeof (struct GNUNET_HashCode)); get_handle->seen_results_end += num_results; queue_filter_messages (get_handle); process_pending_messages (get_handle->dht_handle); }
/** * Iterator over hash map entries that frees all entries * associated with the given client. * * @param cls client to search for in source routes * @param key current key code (ignored) * @param value value in the hash map, a ClientQueryRecord * @return #GNUNET_YES (we should continue to iterate) */ static int remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ClientList *client = cls; struct ClientQueryRecord *record = value; if (record->client != client) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s\n", client, GNUNET_h2s (key)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (forward_map, key, record)); if (NULL != record->hnode) GNUNET_CONTAINER_heap_remove_node (record->hnode); GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0); GNUNET_free (record); return GNUNET_YES; }
/** * Extend path @a path by the @a num_peers from the @a peers * array, assuming the owners past the current owner want it. * * @param path path to extend * @param peers list of peers beyond the end of @a path * @param num_peers length of the @a peers array */ static void extend_path (struct CadetPeerPath *path, struct CadetPeer **peers, unsigned int num_peers) { unsigned int old_len = path->entries_length; struct GNUNET_CONTAINER_HeapNode *hn; int i; /* If we extend an existing path, detach it from the old owner and re-attach to the new one */ hn = NULL; for (i=num_peers-1;i>=0;i--) { /* FIXME: note that path->desirability is used, but not yet updated here! */ hn = GCP_attach_path (peers[i], path, old_len + (unsigned int) i); if (NULL != hn) break; } if (NULL == hn) return; /* none of the peers is interested in this path */ GCP_detach_path (path->entries[old_len-1].peer, path, path->hn); path->hn = hn; GNUNET_array_grow (path->entries, path->entries_length, old_len + i); for (;i >= 0;i--) { struct CadetPeerPathEntry *entry = &path->entries[old_len + i]; entry->peer = peers[i]; entry->path = path; GCP_path_entry_add (entry->peer, entry, old_len + i); } }
/** * Get an available session ID. * * @param sh our handle * @return an unused slot, but never NOT_FOUND (0) */ static uint32_t find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh) { static uint32_t off; uint32_t i; i = 0; while ( ( (NOT_FOUND == off) || (NULL != sh->session_array[off % sh->session_array_size]) ) && (i < sh->session_array_size) ) { off++; i++; } if ( (NOT_FOUND != off % sh->session_array_size) && (NULL == sh->session_array[off % sh->session_array_size]) ) return off; i = sh->session_array_size; GNUNET_array_grow (sh->session_array, sh->session_array_size, sh->session_array_size * 2); return i; }
/** * Callback that processes each of the known HELLOs for the * hostlist response construction. * * @param cls closure, NULL * @param peer id of the peer, NULL for last call * @param hello hello message for the peer (can be NULL) * @param err_msg message */ static void host_processor (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { size_t old; size_t s; int has_addr; if (NULL != err_msg) { GNUNET_assert (NULL == peer); builder->pitr = NULL; GNUNET_free_non_null (builder->data); GNUNET_free (builder); builder = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Error in communication with PEERINFO service: %s\n"), err_msg); return; } if (NULL == peer) { builder->pitr = NULL; finish_response (); return; } if (NULL == hello) return; has_addr = GNUNET_NO; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_has_addr, &has_addr); if (GNUNET_NO == has_addr) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HELLO for peer `%4s' has no address, not suitable for hostlist!\n", GNUNET_i2s (peer)); GNUNET_STATISTICS_update (stats, gettext_noop ("HELLOs without addresses encountered (ignored)"), 1, GNUNET_NO); return; } old = builder->size; s = GNUNET_HELLO_size (hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of `%s' from peer `%s' for hostlist.\n", (unsigned int) s, "HELLO", GNUNET_i2s (peer)); if ( (old + s >= GNUNET_MAX_MALLOC_CHECKED) || (old + s >= MAX_BYTES_PER_HOSTLISTS) ) { /* too large, skip! */ GNUNET_STATISTICS_update (stats, gettext_noop ("bytes not included in hostlist (size limit)"), s, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to hostlist (%u bytes)\n", GNUNET_i2s (peer), (unsigned int) s); GNUNET_array_grow (builder->data, builder->size, old + s); memcpy (&builder->data[old], hello, s); }
/** * Process a given reply that might match the given * request. * * @param cls the `struct GNUNET_DHT_ClientResultMessage` * @param key query of the request * @param value the `struct GNUNET_DHT_RouteHandle` of a request matching the same key * @return #GNUNET_YES to continue to iterate over all results, * #GNUNET_NO if the reply is malformed or we found a matching request */ static int process_reply (void *cls, const struct GNUNET_HashCode *key, void *value) { const struct GNUNET_DHT_ClientResultMessage *dht_msg = cls; struct GNUNET_DHT_GetHandle *get_handle = value; const struct GNUNET_PeerIdentity *put_path; const struct GNUNET_PeerIdentity *get_path; struct GNUNET_HashCode hc; uint32_t put_path_length; uint32_t get_path_length; size_t data_length; size_t msize; size_t meta_length; const void *data; if (dht_msg->unique_id != get_handle->unique_id) { /* UID mismatch */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key), dht_msg->unique_id, get_handle->unique_id); return GNUNET_YES; } msize = ntohs (dht_msg->header.size); put_path_length = ntohl (dht_msg->put_path_length); get_path_length = ntohl (dht_msg->get_path_length); meta_length = sizeof (struct GNUNET_DHT_ClientResultMessage) + sizeof (struct GNUNET_PeerIdentity) * (get_path_length + put_path_length); if ((msize < meta_length) || (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return GNUNET_NO; } data_length = msize - meta_length; LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving %u byte reply for %s to application\n", (unsigned int) data_length, GNUNET_h2s (key)); put_path = (const struct GNUNET_PeerIdentity *) &dht_msg[1]; get_path = &put_path[put_path_length]; data = &get_path[get_path_length]; /* remember that we've seen this result */ GNUNET_CRYPTO_hash (data, data_length, &hc); if (get_handle->seen_results_size == get_handle->seen_results_end) GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_size, get_handle->seen_results_size * 2 + 1); GNUNET_assert (get_handle->seen_results_end == get_handle->seen_results_transmission_offset); get_handle->seen_results[get_handle->seen_results_end++] = hc; /* no need to block it explicitly, service already knows about it! */ get_handle->seen_results_transmission_offset++; get_handle->iter (get_handle->iter_cls, GNUNET_TIME_absolute_ntoh (dht_msg->expiration), key, get_path, get_path_length, put_path, put_path_length, ntohl (dht_msg->type), data_length, data); return GNUNET_NO; }
/** * Actually start the process for the given service. * * @param sl identifies service to start */ static void start_process (struct ServiceList *sl) { char *loprefix; char *options; char *optpos; char *optend; const char *next; int use_debug; char b; char *val; struct ServiceListeningInfo *sli; SOCKTYPE *lsocks; unsigned int ls; /* calculate listen socket list */ lsocks = NULL; ls = 0; for (sli = sl->listen_head; NULL != sli; sli = sli->next) { GNUNET_array_append (lsocks, ls, GNUNET_NETWORK_get_fd (sli->listen_socket)); if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (sli->accept_task); sli->accept_task = GNUNET_SCHEDULER_NO_TASK; } } #if WINDOWS GNUNET_array_append (lsocks, ls, INVALID_SOCKET); #else GNUNET_array_append (lsocks, ls, -1); #endif /* obtain configuration */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX", &loprefix)) loprefix = GNUNET_strdup (prefix_command); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS", &options)) { options = GNUNET_strdup (final_option); if (NULL == strstr (options, "%")) { /* replace '{}' with service name */ while (NULL != (optpos = strstr (options, "{}"))) { optpos[0] = '%'; optpos[1] = 's'; GNUNET_asprintf (&optpos, options, sl->name); GNUNET_free (options); options = optpos; } /* replace '$PATH' with value associated with "PATH" */ while (NULL != (optpos = strstr (options, "$"))) { optend = optpos + 1; while (isupper ((unsigned char) *optend)) optend++; b = *optend; if ('\0' == b) next = ""; else next = optend + 1; *optend = '\0'; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", optpos + 1, &val)) val = GNUNET_strdup (""); *optpos = '\0'; GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next); GNUNET_free (options); GNUNET_free (val); options = optpos; } } } use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG"); /* actually start process */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service `%s' using binary `%s' and configuration `%s'\n", sl->name, sl->binary, sl->config); GNUNET_assert (NULL == sl->proc); if (GNUNET_YES == use_debug) sl->proc = do_start_process (sl->pipe_control, lsocks, loprefix, sl->binary, "-c", sl->config, "-L", "DEBUG", options, NULL); else sl->proc = do_start_process (sl->pipe_control, lsocks, loprefix, sl->binary, "-c", sl->config, options, NULL); if (sl->proc == NULL) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"), sl->name); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name); /* clean up */ GNUNET_free (loprefix); GNUNET_free (options); GNUNET_array_grow (lsocks, ls, 0); }
/** * @brief Remove peer * * @param peer the peer to clean * @return #GNUNET_YES if peer was removed * #GNUNET_NO otherwise */ int Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *peer_ctx; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) { return GNUNET_NO; } peer_ctx = get_peer_ctx (peer); set_peer_flag (peer_ctx, Peers_TO_DESTROY); LOG (GNUNET_ERROR_TYPE_DEBUG, "Going to remove peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); Peers_unset_peer_flag (peer, Peers_ONLINE); GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); while (NULL != peer_ctx->pending_messages_head) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing unsent %s\n", peer_ctx->pending_messages_head->type); remove_pending_message (peer_ctx->pending_messages_head); } /* If we are still waiting for notification whether this peer is live * cancel the according task */ if (NULL != peer_ctx->liveliness_check_pending) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing pending liveliness check for peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); // TODO wait until cadet sets mq->cancel_impl //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev); GNUNET_free (peer_ctx->liveliness_check_pending); peer_ctx->liveliness_check_pending = NULL; } if (NULL != peer_ctx->send_channel) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying send channel\n"); GNUNET_CADET_channel_destroy (peer_ctx->send_channel); peer_ctx->send_channel = NULL; } if (NULL != peer_ctx->recv_channel) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying recv channel\n"); GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); peer_ctx->recv_channel = NULL; } if (NULL != peer_ctx->mq) { GNUNET_MQ_destroy (peer_ctx->mq); peer_ctx->mq = NULL; } GNUNET_free (peer_ctx->send_channel_flags); GNUNET_free (peer_ctx->recv_channel_flags); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id)) { LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n"); } GNUNET_free (peer_ctx); return GNUNET_YES; }
static int check () { #define MAX_TESTVAL 1024 char *ptrs[MAX_TESTVAL]; int i; int j; int k; unsigned int ui; /* GNUNET_malloc/GNUNET_free test */ k = 352; /* random start value */ for (i = 1; i < MAX_TESTVAL; i++) { ptrs[i] = GNUNET_malloc (i); for (j = 0; j < i; j++) ptrs[i][j] = k++; } for (i = MAX_TESTVAL - 1; i >= 1; i--) { for (j = i - 1; j >= 0; j--) if (ptrs[i][j] != (char) --k) return 1; GNUNET_free (ptrs[i]); } /* GNUNET_free_non_null test */ GNUNET_free_non_null (NULL); GNUNET_free_non_null (GNUNET_malloc (4)); /* GNUNET_strdup tests */ ptrs[0] = GNUNET_strdup ("bar"); if (0 != strcmp (ptrs[0], "bar")) return 3; /* now realloc */ ptrs[0] = GNUNET_realloc (ptrs[0], 12); strcpy (ptrs[0], "Hello World"); GNUNET_free (ptrs[0]); GNUNET_asprintf (&ptrs[0], "%s %s", "Hello", "World"); GNUNET_assert (strlen (ptrs[0]) == 11); GNUNET_free (ptrs[0]); /* GNUNET_array_grow tests */ ptrs[0] = NULL; ui = 0; GNUNET_array_grow (ptrs[0], ui, 42); if (ui != 42) return 4; GNUNET_array_grow (ptrs[0], ui, 22); if (ui != 22) return 5; for (j = 0; j < 22; j++) ptrs[0][j] = j; GNUNET_array_grow (ptrs[0], ui, 32); for (j = 0; j < 22; j++) if (ptrs[0][j] != j) return 6; for (j = 22; j < 32; j++) if (ptrs[0][j] != 0) return 7; GNUNET_array_grow (ptrs[0], ui, 0); if (i != 0) return 8; if (ptrs[0] != NULL) return 9; return 0; }
/** * Grow or shrink the size of the sampler. * * @param sampler the sampler to resize. * @param new_size the new size of the sampler */ static void sampler_resize (struct RPS_Sampler *sampler, unsigned int new_size) { unsigned int old_size; uint32_t i; // TODO check min and max size old_size = sampler->sampler_size; if (old_size > new_size) { /* Shrinking */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Shrinking sampler %d -> %d\n", old_size, new_size); to_file (sampler->file_name, "Shrinking sampler %d -> %d", old_size, new_size); for (i = new_size ; i < old_size ; i++) { to_file (sampler->file_name, "-%" PRIu32 ": %s", i, sampler->sampler_elements[i]->file_name); } GNUNET_array_grow (sampler->sampler_elements, sampler->sampler_size, new_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler->sampler_elements now points to %p\n", sampler->sampler_elements); } else if (old_size < new_size) { /* Growing */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Growing sampler %d -> %d\n", old_size, new_size); to_file (sampler->file_name, "Growing sampler %d -> %d", old_size, new_size); GNUNET_array_grow (sampler->sampler_elements, sampler->sampler_size, new_size); for (i = old_size ; i < new_size ; i++) { /* Add new sampler elements */ sampler->sampler_elements[i] = RPS_sampler_elem_create (); to_file (sampler->file_name, "+%" PRIu32 ": %s", i, sampler->sampler_elements[i]->file_name); } } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Size remains the same -- nothing to do\n"); return; } GNUNET_assert (sampler->sampler_size == new_size); }