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); }
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); }
/** * Adds the given node to the gui. */ void nodes_gui_add_node(gnet_node_info_t *info) { static const struct node_data zero_data; struct node_data *data; gnet_node_flags_t flags; g_return_if_fail(info); g_return_if_fail(!htable_contains(nodes_handles, info->node_id)); WALLOC(data); *data = zero_data; data->node_id = nid_ref(info->node_id); data->user_agent = info->vendor ? atom_str_get(info->vendor) : NULL; data->country = info->country; data->host_size = w_concat_strings(&data->host, host_addr_port_to_string(info->addr, info->port), (void *) 0); str_bprintf(data->version, sizeof data->version, "%u.%u", info->proto_major, info->proto_minor); guc_node_fill_flags(data->node_id, &flags); nodes_gui_update_node_flags(data, &flags); htable_insert(nodes_handles, data->node_id, data); gtk_list_store_append(nodes_model, &data->iter); gtk_list_store_set(nodes_model, &data->iter, 0, data, (-1)); }
/** * Writes the browse host data of the context ``ctx'' to the buffer * ``dest''. This must be called multiple times to retrieve the complete * data until zero is returned i.e., the end of file is reached. * * This routine deals with HTML data generation. * * @param ctx an initialized browse host context. * @param dest the destination buffer. * @param size the amount of bytes ``dest'' can hold. * * @return -1 on failure, zero at the end-of-file condition or if size * was zero. On success, the amount of bytes copied to ``dest'' * is returned. */ static ssize_t browse_host_read_html(struct special_upload *ctx, void *const dest, size_t size) { static const char header[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\r\n" "<html>\r\n" "<head>\r\n" "<title>Browse Host</title>\r\n" "</head>\r\n" "<body>\r\n"; static const char trailer[] = "</ul>\r\n</body>\r\n</html>\r\n"; struct browse_host_upload *bh = cast_to_browse_host_upload(ctx); char *p = dest; g_assert(NULL != bh); g_assert(NULL != dest); g_assert(size <= INT_MAX); g_assert(UNSIGNED(bh->state) < NUM_BH_STATES); g_assert(bh->b_size <= INT_MAX); g_assert(bh->b_offset <= bh->b_size); do { switch (bh->state) { case BH_STATE_HEADER: if (!bh->b_data) { bh->b_data = header; bh->b_size = CONST_STRLEN(header); } p += browse_host_read_data(bh, p, &size); if (bh->b_size == bh->b_offset) browse_host_next_state(bh, BH_STATE_LIBRARY_INFO); break; case BH_STATE_LIBRARY_INFO: if (!bh->b_data) { bh->w_buf_size = w_concat_strings(&bh->w_buf, "<h1>", product_get_name(), "</h1>\r\n" "<h3>", version_get_string(), " sharing ", uint64_to_string(shared_files_scanned()), " file", shared_files_scanned() == 1 ? "" : "s", " ", short_kb_size(shared_kbytes_scanned(), GNET_PROPERTY(display_metric_units)), " total</h3>\r\n" "<ul>\r\n", (void *) 0); bh->b_data = bh->w_buf; bh->b_size = bh->w_buf_size - 1; /* minus trailing NUL */ bh->b_offset = 0; } p += browse_host_read_data(bh, p, &size); if (bh->b_size == bh->b_offset) browse_host_next_state(bh, BH_STATE_FILES); break; case BH_STATE_TRAILER: if (!bh->b_data) { bh->b_data = trailer; bh->b_size = CONST_STRLEN(trailer); } p += browse_host_read_data(bh, p, &size); if (bh->b_size == bh->b_offset) browse_host_next_state(bh, BH_STATE_EOF); break; case BH_STATE_FILES: if (bh->b_data && bh->b_size == bh->b_offset) { g_assert(bh->w_buf == bh->b_data); wfree(bh->w_buf, bh->w_buf_size); bh->w_buf = NULL; bh->w_buf_size = 0; bh->b_data = NULL; } if (!bh->b_data) { const shared_file_t *sf; bh->file_index++; sf = shared_file_sorted(bh->file_index); if (!sf) { if (bh->file_index > shared_files_scanned()) browse_host_next_state(bh, BH_STATE_TRAILER); /* Skip holes in the file_index table */ } else if (SHARE_REBUILDING == sf) { browse_host_next_state(bh, BH_STATE_REBUILDING); } else { const char * const name_nfc = shared_file_name_nfc(sf); const filesize_t file_size = shared_file_size(sf); size_t html_size; char *html_name; { const char *dir; char *name; dir = shared_file_relative_path(sf); if (dir) { name = h_strconcat(dir, "/", name_nfc, (void *) 0); } else { name = deconstify_char(name_nfc); } html_size = 1 + html_escape(name, NULL, 0); html_name = walloc(html_size); html_escape(name, html_name, html_size); if (name != name_nfc) { HFREE_NULL(name); } } if (sha1_hash_available(sf)) { const struct sha1 *sha1 = shared_file_sha1(sf); bh->w_buf_size = w_concat_strings(&bh->w_buf, "<li><a href=\"/uri-res/N2R?urn:sha1:", sha1_base32(sha1), "\">", html_name, "</a> [", short_html_size(file_size, GNET_PROPERTY(display_metric_units)), "]</li>\r\n", (void *) 0); } else { char *escaped; escaped = url_escape(name_nfc); bh->w_buf_size = w_concat_strings(&bh->w_buf, "<li><a href=\"/get/", uint32_to_string(shared_file_index(sf)), "/", escaped, "\">", html_name, "</a>" " [", short_html_size(file_size, GNET_PROPERTY(display_metric_units)), "]</li>\r\n", (void *) 0); if (escaped != name_nfc) { HFREE_NULL(escaped); } } wfree(html_name, html_size); bh->b_data = bh->w_buf; bh->b_size = bh->w_buf_size - 1; /* minus trailing NUL */ bh->b_offset = 0; } } if (bh->b_data) p += browse_host_read_data(bh, p, &size); break; case BH_STATE_REBUILDING: if (!bh->b_data) { static const char msg[] = "<li>" "<b>" "The library is currently being rebuild. Please, " "try again in a moment." "</b>" "</li>"; bh->b_data = msg; bh->b_size = CONST_STRLEN(msg); } p += browse_host_read_data(bh, p, &size); if (bh->b_size == bh->b_offset) browse_host_next_state(bh, BH_STATE_TRAILER); break; case BH_STATE_EOF: return p - cast_to_char_ptr(dest); case NUM_BH_STATES: g_assert_not_reached(); } } while (size > 0); return p - cast_to_char_ptr(dest); }