static inline void nodes_gui_reverse_lookup_selected_helper(GtkTreeModel *model, GtkTreePath *unused_path, GtkTreeIter *iter, gpointer unused_data) { struct node_data *data; gnet_node_info_t info; (void) unused_path; (void) unused_data; gtk_tree_model_get(model, iter, 0, &data, (-1)); g_assert(NULL != find_node(data->node_id)); if (hset_contains(ht_pending_lookups, data->node_id)) return; guc_node_fill_info(data->node_id, &info); g_assert(data->node_id == info.node_id); if (!info.is_pseudo) { const struct nid *key = nid_ref(data->node_id); WFREE_NULL(data->host, data->host_size); data->host_size = w_concat_strings(&data->host, _("Reverse lookup in progress..."), " (", host_addr_port_to_string(info.addr, info.port), ")", (void *) 0); hset_insert(ht_pending_lookups, key); adns_reverse_lookup(info.addr, host_lookup_callback, deconstify_gpointer(nid_ref(key))); } guc_node_clear_info(&info); }
static inline void update_row(const void *key, void *value, void *user_data) { struct node_data *data = value; time_t *now_ptr = user_data, now = *now_ptr; gnet_node_status_t status; g_assert(NULL != data); g_assert(data->node_id == key); if (!guc_node_get_status(data->node_id, &status)) return; /* * Update additional info too if it has recorded changes. */ if (remove_item(ht_node_info_changed, data->node_id)) { gnet_node_info_t info; if (guc_node_fill_info(data->node_id, &info)) { nodes_gui_update_node_info(data, &info); guc_node_clear_info(&info); } } if (remove_item(ht_node_flags_changed, data->node_id)) { gnet_node_flags_t flags; if (guc_node_fill_flags(data->node_id, &flags)) { nodes_gui_update_node_flags(data, &flags); } } if (status.connect_date) data->connected = delta_time(now, status.connect_date); if (status.up_date) data->uptime = delta_time(now, status.up_date); /* Update the status line */ { const gchar *s; size_t size; s = nodes_gui_common_status_str(&status); size = 1 + strlen(s); if (size > data->info_size) { WFREE_NULL(data->info, data->info_size); data->info = wcopy(s, size); data->info_size = size; } else { memcpy(data->info, s, size); } } tree_model_iter_changed(GTK_TREE_MODEL(nodes_model), &data->iter); }
static void host_lookup_callback(const gchar *hostname, gpointer key) { const struct nid *node_id = key; gnet_node_info_t info; struct node_data *data; host_addr_t addr; guint16 port; if (!ht_pending_lookups) goto finish; if (!remove_item(ht_pending_lookups, node_id)) goto finish; data = find_node(node_id); if (!data) goto finish; guc_node_fill_info(node_id, &info); g_assert(node_id == info.node_id); addr = info.addr; port = info.port; guc_node_clear_info(&info); WFREE_NULL(data->host, data->host_size); if (hostname) { const gchar *host; gchar *to_free; if (utf8_is_valid_string(hostname)) { to_free = NULL; host = hostname; } else { to_free = locale_to_utf8_normalized(hostname, UNI_NORM_GUI); host = to_free; } data->host_size = w_concat_strings(&data->host, host, " (", host_addr_port_to_string(addr, port), ")", (void *) 0); G_FREE_NULL(to_free); } else { statusbar_gui_warning(10, _("Reverse lookup for %s failed"), host_addr_to_string(addr)); data->host_size = w_concat_strings(&data->host, host_addr_port_to_string(addr, port), (void *) 0); } finish: nid_unref(node_id); }
/** * Callback: called when a node is added from the backend. * * Adds the node to the gui. */ static void nodes_gui_node_added(const struct nid *node_id) { gnet_node_info_t info; if (GUI_PROPERTY(gui_debug) >= 5) g_debug("%s(%s)", G_STRFUNC, nid_to_string(node_id)); guc_node_fill_info(node_id, &info); nodes_gui_add_node(&info); guc_node_clear_info(&info); }
/** * Update all the nodes at the same time. * * @bug * FIXME: We should remember for every node when it was last * updated and only refresh every node at most once every * second. This information should be kept in a struct pointed * to by the row user_data and should be automatically freed * when removing the row (see upload stats code). */ void nodes_gui_update_display(time_t now) { GtkCList *clist; GList *l; gint row = 0; gnet_node_status_t status; clist = GTK_CLIST(gui_main_window_lookup("clist_nodes")); gtk_clist_freeze(clist); for (l = clist->row_list, row = 0; l; l = l->next, row++) { const struct nid *node_id = ((GtkCListRow *) l->data)->data; guc_node_get_status(node_id, &status); /* * Update additional info too if it has recorded changes. */ if (remove_item(hs_node_info_changed, node_id)) { gnet_node_info_t info; guc_node_fill_info(node_id, &info); nodes_gui_update_node_info(&info, row); guc_node_clear_info(&info); } if (remove_item(hs_node_flags_changed, node_id)) { gnet_node_flags_t flags; guc_node_fill_flags(node_id, &flags); nodes_gui_update_node_flags(node_id, &flags, -1); } /* * Don't update times if we've already disconnected. */ if (status.status == GTA_NODE_CONNECTED) { gtk_clist_set_text(clist, row, c_gnet_connected, short_uptime(delta_time(now, status.connect_date))); if (status.up_date) gtk_clist_set_text(clist, row, c_gnet_uptime, status.up_date ? short_uptime(delta_time(now, status.up_date)) : "..."); } gtk_clist_set_text(clist, row, c_gnet_info, nodes_gui_common_status_str(&status)); } gtk_clist_thaw(clist); }
static void update_tooltip(GtkTreeView *tv, GtkTreePath *path) { const struct node_data *data = NULL; GtkTreeModel *model; GtkTreeIter iter; g_assert(tv != NULL); if (path) { GtkTreeIter parent; model = gtk_tree_view_get_model(tv); if (!gtk_tree_model_get_iter(model, &iter, path)) { g_warning("gtk_tree_model_get_iter() failed"); return; } if (gtk_tree_model_iter_parent(model, &parent, &iter)) iter = parent; gtk_tree_model_get(model, &iter, 0, &data, (-1)); } if (data && find_node(data->node_id)) { gnet_node_info_t info; gnet_node_flags_t flags; gchar text[1024]; guc_node_fill_flags(data->node_id, &flags); guc_node_fill_info(data->node_id, &info); g_assert(info.node_id == data->node_id); str_bprintf(text, sizeof text, "%s %s\n" "%s %s (%s)\n" "%s %s (%s)\n" "%s %.64s", _("Peer:"), host_addr_port_to_string(info.gnet_addr, info.gnet_port), _("Peermode:"), guc_node_peermode_to_string(flags.peermode), flags.incoming ? _("incoming") : _("outgoing"), _("Country:"), iso3166_country_name(info.country), iso3166_country_cc(info.country), _("Vendor:"), info.vendor ? info.vendor : _("Unknown")); guc_node_clear_info(&info); gtk_tooltips_set_tip(settings_gui_tooltips(), GTK_WIDGET(tv), text, NULL); } else { GtkWidget *w; gtk_tooltips_set_tip(settings_gui_tooltips(), GTK_WIDGET(tv), _("Move the cursor over a row to see details."), NULL); w = settings_gui_tooltips()->tip_window; if (w) gtk_widget_hide(w); } }