/** * Removes a queue entry of an operation from one of the operation queues' lists * depending on the state of the operation * * @param op the operation whose entry has to be removed * @param index the index of the entry in the operation's array of queue entries */ static void remove_queue_entry (struct GNUNET_TESTBED_Operation *op, unsigned int index) { struct OperationQueue *opq; struct QueueEntry *entry; opq = op->queues[index]; entry = op->qentries[index]; switch (op->state) { case OP_STATE_INIT: GNUNET_assert (0); break; case OP_STATE_WAITING: GNUNET_CONTAINER_DLL_remove (opq->wq_head, opq->wq_tail, entry); break; case OP_STATE_READY: GNUNET_CONTAINER_DLL_remove (opq->rq_head, opq->rq_tail, entry); break; case OP_STATE_ACTIVE: GNUNET_CONTAINER_DLL_remove (opq->aq_head, opq->aq_tail, entry); break; case OP_STATE_INACTIVE: GNUNET_CONTAINER_DLL_remove (opq->nq_head, opq->nq_tail, entry); break; } }
/** * Notifies a tree that a connection it might be using is broken. * Marks all peers down the paths as disconnected and notifies the client. * * @param t Tree to use. * @param p1 Short id of one of the peers (order unimportant) * @param p2 Short id of one of the peers (order unimportant) * @param cb Function to call for every peer that is marked as disconnected. * @param cbcls Closure for cb. * * @return Short ID of the first disconnected peer in the tree. */ GNUNET_PEER_Id tree_notify_connection_broken (struct MeshTunnelTree *t, GNUNET_PEER_Id p1, GNUNET_PEER_Id p2, MeshTreeCallback cb, void *cbcls) { struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *c; n = tree_find_peer (t, p1); if (NULL == n) return 0; if (NULL != n->parent && n->parent->peer == p2) { tree_mark_peers_disconnected (t, n, cb, cbcls); GNUNET_CONTAINER_DLL_remove (n->parent->children_head, n->parent->children_tail, n); GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, n); return p1; } for (c = n->children_head; NULL != c; c = c->next) { if (c->peer == p2) { tree_mark_peers_disconnected (t, c, cb, cbcls); GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c); GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, c); return p2; } } return 0; }
static void stop_report_addresses (struct Plugin *plugin) { /* Stop NAT handle */ GNUNET_NAT_unregister (plugin->nat); /* Clean up addresses */ struct IPv4HttpAddressWrapper *w_t4; struct IPv6HttpAddressWrapper *w_t6; while (plugin->ipv4_addr_head != NULL) { w_t4 = plugin->ipv4_addr_head; GNUNET_CONTAINER_DLL_remove (plugin->ipv4_addr_head, plugin->ipv4_addr_tail, w_t4); GNUNET_free (w_t4); } while (plugin->ipv6_addr_head != NULL) { w_t6 = plugin->ipv6_addr_head; GNUNET_CONTAINER_DLL_remove (plugin->ipv6_addr_head, plugin->ipv6_addr_tail, w_t6); GNUNET_free (w_t6); } }
/** * Cancel the specified transmission-ready notification. * * @param th handle that was returned by "notify_transmit_ready". */ void GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th) { struct PeerRecord *pr = th->peer; struct GNUNET_CORE_Handle *h; GNUNET_assert (NULL != th); GNUNET_assert (NULL != pr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Aborting transmission request to core for %u bytes to `%s'\n", (unsigned int) th->msize, GNUNET_i2s (&pr->peer)); th->peer = NULL; h = pr->ch; if (NULL != th->cm) { /* we're currently in the control queue, remove */ GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, th->cm); GNUNET_free (th->cm); th->cm = NULL; } if ((NULL != pr->prev) || (NULL != pr->next) || (pr == h->ready_peer_head)) { /* the request that was 'approved' by core was * canceled before it could be transmitted; remove * us from the 'ready' list */ GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); } if (GNUNET_SCHEDULER_NO_TASK != pr->ntr_task) { GNUNET_SCHEDULER_cancel (pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; } }
/** * Cancel sending the message. Message must have been sent with * #GNUNET_MQ_send before. May not be called after the notify sent * callback has been called * * @param ev queued envelope to cancel */ void GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev) { struct GNUNET_MQ_Handle *mq = ev->parent_queue; GNUNET_assert (NULL != mq); GNUNET_assert (NULL != mq->cancel_impl); if (mq->current_envelope == ev) { // complex case, we already started with transmitting // the message mq->cancel_impl (mq, mq->impl_state); // continue sending the next message, if any if (NULL == mq->envelope_head) { mq->current_envelope = NULL; } else { mq->current_envelope = mq->envelope_head; GNUNET_CONTAINER_DLL_remove (mq->envelope_head, mq->envelope_tail, mq->current_envelope); mq->send_impl (mq, mq->current_envelope->mh, mq->impl_state); } } else { // simple case, message is still waiting in the queue GNUNET_CONTAINER_DLL_remove (mq->envelope_head, mq->envelope_tail, ev); } ev->parent_queue = NULL; ev->mh = NULL; GNUNET_free (ev); }
/** * Stop an active NAT test. * * @param tst test to stop. */ void GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) { struct NatActivity *pos; struct ClientActivity *cpos; LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping NAT test\n"); while (NULL != (cpos = tst->ca_head)) { GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, cpos); GNUNET_CLIENT_disconnect (cpos->client); GNUNET_free (cpos); } while (NULL != (pos = tst->na_head)) { GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, pos); GNUNET_SCHEDULER_cancel (pos->rtask); GNUNET_NETWORK_socket_close (pos->sock); GNUNET_free (pos); } if (NULL != tst->ttask) GNUNET_SCHEDULER_cancel (tst->ttask); if (NULL != tst->ltask) GNUNET_SCHEDULER_cancel (tst->ltask); if (NULL != tst->lsock) GNUNET_NETWORK_socket_close (tst->lsock); if (NULL != tst->nat) GNUNET_NAT_unregister (tst->nat); GNUNET_free (tst); }
/** * Cancel a PSYCstore operation. Note that the operation MAY still * be executed; this merely cancels the continuation; if the request * was already transmitted, the service may still choose to complete * the operation. * * @param op Operation to cancel. */ void GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op) { struct GNUNET_PSYCSTORE_Handle *h = op->h; if (h->transmit_head != NULL && (h->transmit_head != op || NULL == h->client)) { /* request not active, can simply remove */ GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op); GNUNET_free (op); return; } if (NULL != h->th) { /* request active but not yet with service, can still abort */ GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op); GNUNET_free (op); transmit_next (h); return; } /* request active with service, simply ensure continuations are not called */ op->res_cb = NULL; op->data_cb = NULL; }
/** * Message timed out. Remove it from the queue. * * @param cls the message (struct ARMControlMessage *) * @param tc task context */ static void control_message_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ARMControlMessage *cm = cls; struct GNUNET_ARM_Message *arm_msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Control message timed out\n"); arm_msg = cm->msg; if ((NULL == arm_msg) || (0 == arm_msg->request_id)) { GNUNET_CONTAINER_DLL_remove (cm->h->control_pending_head, cm->h->control_pending_tail, cm); } else { GNUNET_CONTAINER_DLL_remove (cm->h->control_sent_head, cm->h->control_sent_tail, cm); } if (NULL != cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_TIMEOUT, NULL, 0); else if (NULL != cm->list_cont) cm->list_cont (cm->cont_cls, GNUNET_ARM_REQUEST_TIMEOUT, 0, NULL); GNUNET_free_non_null (cm->msg); GNUNET_free (cm); }
/** * Delete the current path to the peer, including all now unused relays. * The destination peer is NOT destroyed, it is returned in order to either set * a new path to it or destroy it explicitly, taking care of it's child nodes. * * @param t Tunnel tree where to delete the path from. * @param peer_id Short ID of the destination peer whose path we want to remove. * @param cb Callback to use to notify about disconnected peers. * @param cbcls Closure for cb. * * @return pointer to the pathless node. * NULL when not found */ struct MeshTunnelTreeNode * tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, MeshTreeCallback cb, void *cbcls) { struct MeshTunnelTreeNode *parent; struct MeshTunnelTreeNode *node; struct MeshTunnelTreeNode *n; #if MESH_TREE_DEBUG struct GNUNET_PeerIdentity id; GNUNET_PEER_resolve (peer_id, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting path to %s.\n", GNUNET_i2s (&id)); #endif if (peer_id == t->root->peer) return NULL; for (n = t->disconnected_head; NULL != n; n = n->next) { if (n->peer == peer_id) { /* Was already pathless, waiting for reconnection */ GNUNET_CONTAINER_DLL_remove (t->disconnected_head, t->disconnected_tail, n); return n; } } n = tree_find_peer (t, peer_id); if (NULL == n) return NULL; node = n; parent = n->parent; GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, n); n->parent = NULL; while (MESH_PEER_RELAY == parent->status && NULL == parent->children_head) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting node %s.\n", GNUNET_i2s (&id)); #endif n = parent->parent; tree_node_destroy (parent); parent = n; } #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Not deleted peer %s.\n", GNUNET_i2s (&id)); #endif tree_mark_peers_disconnected (t, node, cb, cbcls); return node; }
static void nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct IPv4HttpAddressWrapper *w_t4 = NULL; struct IPv6HttpAddressWrapper *w_t6 = NULL; int af; af = addr->sa_family; switch (af) { case AF_INET: w_t4 = find_address (plugin, addr, addrlen); if (w_t4 == NULL) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove IPv4 address `%s'\n", http_plugin_address_to_string (NULL, &w_t4->addr, sizeof (struct IPv4HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr, sizeof (struct IPv4HttpAddress)); GNUNET_CONTAINER_DLL_remove (plugin->ipv4_addr_head, plugin->ipv4_addr_tail, w_t4); GNUNET_free (w_t4); break; case AF_INET6: w_t6 = find_address (plugin, addr, addrlen); if (w_t6 == NULL) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove IPv6 address `%s'\n", http_plugin_address_to_string (NULL, &w_t6->addr6, sizeof (struct IPv6HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6, sizeof (struct IPv6HttpAddress)); GNUNET_CONTAINER_DLL_remove (plugin->ipv6_addr_head, plugin->ipv6_addr_tail, w_t6); GNUNET_free (w_t6); break; default: return; } }
/** * End the session with the given peer (we are no longer * connected). * * @param pid identity of peer to kill session with */ void GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid) { struct Session *session; struct GSC_ClientActiveRequest *car; struct SessionMessageEntry *sme; session = find_session (pid); if (NULL == session) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying session for peer `%4s'\n", GNUNET_i2s (&session->peer)); if (NULL != session->cork_task) { GNUNET_SCHEDULER_cancel (session->cork_task); session->cork_task = NULL; } while (NULL != (car = session->active_client_request_head)) { GNUNET_CONTAINER_DLL_remove (session->active_client_request_head, session->active_client_request_tail, car); GSC_CLIENTS_reject_request (car, GNUNET_NO); } while (NULL != (sme = session->sme_head)) { GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme); GNUNET_free (sme); } if (NULL != session->typemap_task) { GNUNET_SCHEDULER_cancel (session->typemap_task); session->typemap_task = NULL; } GSC_CLIENTS_notify_clients_about_neighbour (&session->peer, session->tmap, NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (sessions, &session->peer, session)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (sessions), GNUNET_NO); GSC_TYPEMAP_destroy (session->tmap); session->tmap = NULL; GNUNET_free (session); }
/** * Cancel pending lookup request * * @param lr the lookup request to cancel */ void GNUNET_GNS_cancel_lookup_request (struct GNUNET_GNS_LookupRequest *lr) { struct PendingMessage *p = (struct PendingMessage*) &lr[1]; GNUNET_assert (NULL != lr->gns_handle); if (GNUNET_NO == p->transmitted) GNUNET_CONTAINER_DLL_remove (lr->gns_handle->pending_head, lr->gns_handle->pending_tail, p); GNUNET_CONTAINER_DLL_remove (lr->gns_handle->lookup_head, lr->gns_handle->lookup_tail, lr); GNUNET_free (lr); }
/** * Cancel pending shorten request * * @param sr the lookup request to cancel */ void GNUNET_GNS_cancel_shorten_request (struct GNUNET_GNS_ShortenRequest *sr) { struct PendingMessage *p = (struct PendingMessage*) &sr[1]; GNUNET_assert (NULL != sr->gns_handle); if (GNUNET_NO == p->transmitted) GNUNET_CONTAINER_DLL_remove (sr->gns_handle->pending_head, sr->gns_handle->pending_tail, p); GNUNET_CONTAINER_DLL_remove (sr->gns_handle->shorten_head, sr->gns_handle->shorten_tail, sr); GNUNET_free (sr); }
/** * Abort send operation (naturally, the message may have * already been transmitted; this only stops the 'cb' * from being called again). * * @param th send operation to cancel */ void GNUNET_DV_send_cancel (struct GNUNET_DV_TransmitHandle *th) { struct GNUNET_DV_ServiceHandle *sh = th->sh; if (NULL == th->msg) GNUNET_CONTAINER_DLL_remove (th->target->head, th->target->tail, th); else GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, th); GNUNET_free (th); }
/** * Cancel pending get auth request * * @param gar the lookup request to cancel */ void GNUNET_GNS_cancel_get_auth_request (struct GNUNET_GNS_GetAuthRequest *gar) { struct PendingMessage *p = (struct PendingMessage*) &gar[1]; GNUNET_assert (NULL != gar->gns_handle); if (GNUNET_NO == p->transmitted) GNUNET_CONTAINER_DLL_remove (gar->gns_handle->pending_head, gar->gns_handle->pending_tail, p); GNUNET_CONTAINER_DLL_remove (gar->gns_handle->get_auth_head, gar->gns_handle->get_auth_tail, gar); GNUNET_free (gar); }
/** * Add or remove an address from this peer's HELLO message. * * @param addremove GNUNET_YES to add, GNUNET_NO to remove * @param address address to add or remove */ void GST_hello_modify_addresses (int addremove, const struct GNUNET_HELLO_Address *address) { struct OwnAddressList *al; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, (addremove == GNUNET_YES) ? "Adding `%s' to the set of our addresses\n" : "Removing `%s' from the set of our addresses\n", GST_plugins_a2s (address)); GNUNET_assert (address != NULL); if (GNUNET_NO == addremove) { for (al = oal_head; al != NULL; al = al->next) if (0 == GNUNET_HELLO_address_cmp (address, al->address)) { GNUNET_CONTAINER_DLL_remove (oal_head, oal_tail, al); GNUNET_HELLO_address_free (al->address); GNUNET_free (al); refresh_hello (); return; } /* address to be removed not found!? */ GNUNET_break (0); return; } al = GNUNET_malloc (sizeof (struct OwnAddressList)); GNUNET_CONTAINER_DLL_insert (oal_head, oal_tail, al); al->address = GNUNET_HELLO_address_copy (address); refresh_hello (); }
/** * Iterate over all nodes in the tree. * * @param tree Tree to use.. * @param cb Callback to call over each child. * @param cb_cls Closure for @c cb. * * TODO: recursive implementation? (s/heap/stack/g) */ void tree_iterate_all (struct MeshTunnelTree *tree, MeshWholeTreeCallback cb, void *cb_cls) { struct MeshTunnelTreeNode *parent; struct MeshTunnelTreeNode *n; struct MeshTreePendingNode *head; struct MeshTreePendingNode *tail; struct MeshTreePendingNode *pending; cb (cb_cls, tree->root->peer, 0); pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode)); pending->node = tree->root; head = tail = NULL; GNUNET_CONTAINER_DLL_insert (head, tail, pending); while (NULL != head) { pending = head; parent = pending->node; GNUNET_CONTAINER_DLL_remove (head, tail, pending); GNUNET_free (pending); for (n = parent->children_head; NULL != n; n = n->next) { cb (cb_cls, n->peer, parent->peer); pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode)); pending->node = n; /* Insert_tail: breadth first, Insert: depth first */ GNUNET_CONTAINER_DLL_insert (head, tail, pending); } } }
/** * Destroys and frees the node and all children * * @param parent Parent node to be destroyed */ static void tree_node_destroy (struct MeshTunnelTreeNode *parent) { struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *next; #if MESH_TREE_DEBUG struct GNUNET_PeerIdentity id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying node %u\n", parent->peer); GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: (%s)\n", GNUNET_i2s (&id)); #endif n = parent->children_head; while (NULL != n) { next = n->next; tree_node_destroy (n); n = next; } GNUNET_PEER_change_rc (parent->peer, -1); if (NULL != parent->parent) GNUNET_CONTAINER_DLL_remove (parent->parent->children_head, parent->parent->children_tail, parent); GNUNET_free (parent); }
/** * A client disconnected. Remove all of its data structure entries. * * @param cls closure, NULL * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientEntry *ce; struct ClientEntry *nx; nx = client_head; for (ce = nx; NULL != ce; ce = nx) { nx = ce->next; if (ce->client == client) { if (NULL != ce->refresh_task) { GNUNET_SCHEDULER_cancel (ce->refresh_task); ce->refresh_task = NULL; } if (NULL != ce->ah) { REGEX_INTERNAL_announce_cancel (ce->ah); ce->ah = NULL; } if (NULL != ce->sh) { REGEX_INTERNAL_search_cancel (ce->sh); ce->sh = NULL; } GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); GNUNET_free (ce); } } }
/** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Ego *e; if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_CONFIGURATION_destroy (subsystem_cfg); subsystem_cfg = NULL; GNUNET_free (subsystem_cfg_file); subsystem_cfg_file = NULL; GNUNET_free (ego_directory); ego_directory = NULL; while (NULL != (e = ego_head)) { GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, e); GNUNET_free (e->pk); GNUNET_free (e->identifier); GNUNET_free (e); } }
/** * Kill a #Slave object * * @param slave the #Slave object */ static void kill_slave (struct Slave *slave) { struct HostRegistration *hr_entry; while (NULL != (hr_entry = slave->hr_dll_head)) { GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr_entry); GNUNET_free (hr_entry); } if (NULL != slave->rhandle) GNUNET_TESTBED_cancel_registration (slave->rhandle); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, reghost_free_iterator, slave)); GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map); if (NULL != slave->controller) GNUNET_TESTBED_controller_disconnect (slave->controller); if (NULL != slave->controller_proc) { LOG_DEBUG ("Stopping a slave\n"); GNUNET_TESTBED_controller_kill_ (slave->controller_proc); } }
/** * Cleans up the queue used for forwarding link controllers requests */ void GST_free_lcf () { struct LCFContext *lcf; if (NULL != lcf_head) { if (NULL != lcf_proc_task_id) { GNUNET_SCHEDULER_cancel (lcf_proc_task_id); lcf_proc_task_id = NULL; } } GNUNET_assert (NULL == lcf_proc_task_id); for (lcf = lcf_head; NULL != lcf; lcf = lcf_head) { if (NULL != lcf->op) GNUNET_TESTBED_operation_done (lcf->op); if (NULL != lcf->timeout_task) GNUNET_SCHEDULER_cancel (lcf->timeout_task); GNUNET_CONTAINER_DLL_remove (lcf_head, lcf_tail, lcf); GNUNET_free (lcf); } }
/** * Cancel the request for opening a connection to the neighbour * * @param h the notification handle */ void GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h) { struct Neighbour *n; int cleanup_task; n = h->n; cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO; GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); GNUNET_free (h); if (GNUNET_NO == cleanup_task) return; if (NULL == n->notify_task) return; GNUNET_assert (0 < n->reference_cnt); n->reference_cnt--; GNUNET_SCHEDULER_cancel (n->notify_task); n->notify_task = NULL; if (NULL == n->nl_head) { if ( (0 == n->reference_cnt) && (0 == n->inactive) ) { n->inactive = 1; GNUNET_TESTBED_operation_inactivate_ (n->conn_op); } return; } trigger_notifications (n); }
/** * Stop monitoring. * * @param handle The handle to the monitor request returned by monitor_start. * * On return get_handle will no longer be valid, caller must not use again!!! */ void GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *handle) { struct GNUNET_DHT_MonitorStartStopMessage *m; struct PendingMessage *pending; GNUNET_CONTAINER_DLL_remove (handle->dht_handle->monitor_head, handle->dht_handle->monitor_tail, handle); pending = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorStartStopMessage) + sizeof (struct PendingMessage)); m = (struct GNUNET_DHT_MonitorStartStopMessage *) &pending[1]; pending->msg = &m->header; pending->handle = handle->dht_handle; pending->free_on_send = GNUNET_YES; m->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP); m->header.size = htons (sizeof (struct GNUNET_DHT_MonitorStartStopMessage)); m->type = htonl(handle->type); m->get = htons(NULL != handle->get_cb); m->get_resp = htons(NULL != handle->get_resp_cb); m->put = htons(NULL != handle->put_cb); if (NULL != handle->key) { m->filter_key = htons(1); memcpy (&m->key, handle->key, sizeof(GNUNET_HashCode)); } GNUNET_CONTAINER_DLL_insert (handle->dht_handle->pending_head, handle->dht_handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; process_pending_messages (handle->dht_handle); GNUNET_free_non_null (handle->key); GNUNET_free (handle); }
/** * Disconnect from DV service. * * @param sh service handle */ void GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh) { struct GNUNET_DV_TransmitHandle *pos; if (NULL == sh) return; if (NULL != sh->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (sh->th); sh->th = NULL; } while (NULL != (pos = sh->th_head)) { GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, pos); GNUNET_free (pos); } if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } GNUNET_CONTAINER_multipeermap_iterate (sh->peers, &cleanup_send_cb, sh); GNUNET_CONTAINER_multipeermap_destroy (sh->peers); GNUNET_free (sh); }
/** * Destroy a given client peer context * * @param cp client peer context */ static void destroy_clientpeer (struct ClientPeerContext *cp) { struct PendingMessage *pm; cp->destroying = GNUNET_YES; if (NULL != cp->th) { GNUNET_CADET_notify_transmit_ready_cancel (cp->th); cp->th = NULL; } pm = cp->pm_head; while (NULL != pm) { GNUNET_CONTAINER_DLL_remove (cp->pm_head, cp->pm_tail, pm); GNUNET_free (pm->msg); GNUNET_free (pm); pm = cp->pm_head; } if (NULL != cp->ch) { GNUNET_CADET_channel_destroy (cp->ch); cp->ch = NULL; } GNUNET_free (cp); }
/** * Function called to notify a client about the socket * begin ready to queue more data. "buf" will be * NULL and "size" zero if the socket was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_callback (void *cls, size_t size, void *buf) { struct TransmitCallbackContext *tcc = cls; size_t msize; tcc->th = NULL; GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc); msize = ntohs (tcc->msg->size); if (size == 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Transmission to client failed!\n")); GNUNET_SERVER_receive_done (tcc->client, GNUNET_SYSERR); GNUNET_SERVER_client_drop (tcc->client); GNUNET_free (tcc->msg); GNUNET_free (tcc); return 0; } GNUNET_assert (size >= msize); memcpy (buf, tcc->msg, msize); GNUNET_SERVER_receive_done (tcc->client, GNUNET_OK); GNUNET_SERVER_client_drop (tcc->client); GNUNET_free (tcc->msg); GNUNET_free (tcc); return msize; }
/** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientPeerContext *cp; cp = cp_head; while (NULL != cp) { GNUNET_CONTAINER_DLL_remove (cp_head, cp_tail, cp); destroy_clientpeer (cp); cp = cp_head; } if (NULL != cadet) { GNUNET_CADET_disconnect (cadet); cadet = NULL; } if (NULL != peerstore) { GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES); peerstore = NULL; } GNUNET_SENSOR_destroy_sensors (sensors); if (NULL != sensor_dir) { GNUNET_free (sensor_dir); sensor_dir = NULL; } GNUNET_SCHEDULER_shutdown (); }
/** * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready * request. A ClientList is passed as closure, take the head of the list * and copy it into buf, which has the result of sending the message to the * client. * * @param cls closure to this call * @param size maximum number of bytes available to send * @param buf where to copy the actual message to * * @return the number of bytes actually copied, 0 indicates failure */ static size_t send_reply_to_client (void *cls, size_t size, void *buf) { struct ClientList *client = cls; char *cbuf = buf; struct PendingMessage *reply; size_t off; size_t msize; client->transmit_handle = NULL; if (buf == NULL) { /* client disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected, pending messages will be discarded\n", client->client_handle); return 0; } off = 0; while ((NULL != (reply = client->pending_head)) && (size >= off + (msize = ntohs (reply->msg->size)))) { GNUNET_CONTAINER_DLL_remove (client->pending_head, client->pending_tail, reply); memcpy (&cbuf[off], reply->msg, msize); GNUNET_free (reply); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to client %p\n", msize, client->client_handle); off += msize; } process_pending_messages (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u/%u bytes to client %p\n", (unsigned int) off, (unsigned int) size, client->client_handle); return off; }
/** * Function called to notify a client about the connection begin ready to queue * more data. "buf" will be NULL and "size" zero if the connection was closed * for writing in the meantime. * * @param cls NULL * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_notify (void *cls, size_t size, void *buf) { struct MessageQueue *mq_entry; transmit_handle = NULL; mq_entry = mq_head; GNUNET_assert (NULL != mq_entry); if (0 == size) return 0; GNUNET_assert (ntohs (mq_entry->msg->size) <= size); size = ntohs (mq_entry->msg->size); memcpy (buf, mq_entry->msg, size); GNUNET_free (mq_entry->msg); GNUNET_SERVER_client_drop (mq_entry->client); GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); GNUNET_free (mq_entry); mq_entry = mq_head; if (NULL != mq_entry) transmit_handle = GNUNET_SERVER_notify_transmit_ready (mq_entry->client, ntohs (mq_entry->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_ready_notify, NULL); return size; }