void upload_stats_gui_add(struct ul_stats *us) { GtkCList *clist = clist_ul_stats(); const gchar *rowdata[c_us_num]; enum c_us i; int row; char size_tmp[16]; char attempts_tmp[16]; char complete_tmp[16]; char norm_tmp[16]; char rtime_tmp[64]; char dtime_tmp[64]; g_strlcpy(size_tmp, short_size(us->size, show_metric_units()), sizeof size_tmp); gm_snprintf(attempts_tmp, sizeof attempts_tmp, "%u", us->attempts); gm_snprintf(complete_tmp, sizeof complete_tmp, "%u", us->complete); gm_snprintf(norm_tmp, sizeof norm_tmp, "%.3f", us->norm); if (us->rtime) { timestamp_to_string_buf(us->rtime, rtime_tmp, sizeof rtime_tmp); } else { rtime_tmp[0] = '\0'; } if (us->dtime) { timestamp_to_string_buf(us->dtime, dtime_tmp, sizeof dtime_tmp); } else { dtime_tmp[0] = '\0'; } for (i = 0; i < c_us_num; i++) switch (i) { case c_us_filename: rowdata[i] = lazy_utf8_to_ui_string(us->filename); break; case c_us_size: rowdata[i] = size_tmp; break; case c_us_attempts: rowdata[i] = attempts_tmp; break; case c_us_complete: rowdata[i] = complete_tmp; break; case c_us_norm: rowdata[i] = norm_tmp; break; case c_us_rtime: rowdata[i] = rtime_tmp; break; case c_us_dtime: rowdata[i] = dtime_tmp; break; case c_us_num: g_assert_not_reached(); } row = gtk_clist_append(clist, deconstify_gpointer(rowdata)); g_return_if_fail(row >= 0); ul_stats_set_row(us, row); gtk_clist_set_row_data_full(clist, row, us, on_clist_ul_stats_row_removed); /* FIXME: should use auto_sort? */ if (0 == clist->freeze_count) { gtk_clist_sort(clist); clist_sync_rows(clist, on_clist_ul_stats_row_moved); } }
/** * helper func for stats_display - * does two things: * * - clears out aged / infrequent search terms * - sticks the rest of the search terms in clist_search_stats * */ static gboolean stats_hash_to_clist(gpointer key, gpointer value, gpointer unused_udata) { gchar *text[3]; gchar period_tmp[32]; gchar total_tmp[32]; struct term_counts *val = value; (void) unused_udata; /* update counts */ if (!val->period_cnt) val->periods++; else val->periods = 0; val->total_cnt += val->period_cnt; /* try to keep the number of infrequent terms down */ if ( (1.0 * val->total_cnt / (val->periods + 2.0)) * 100 < GUI_PROPERTY(search_stats_delcoef) ) { G_FREE_NULL(key); G_FREE_NULL(val); return TRUE; } stat_count++; /* update the display */ /* FIXME: make %8.8d %d and set up custom sort function */ gm_snprintf(period_tmp, sizeof period_tmp, "%8.8d", (int) val->period_cnt); gm_snprintf(total_tmp, sizeof total_tmp, "%8.8d", (int) val->total_cnt); text[0] = key; text[1] = period_tmp; text[2] = total_tmp; { GtkWidget *clist_search_stats = gui_main_window_lookup("clist_search_stats"); gtk_clist_insert(GTK_CLIST(clist_search_stats), 0, text); } /* new period begins */ val->period_cnt = 0; return FALSE; }
/** * Adds the given node to the gui. */ void nodes_gui_add_node(gnet_node_info_t *n) { GtkCList *clist_nodes; const gchar *titles[c_gnet_num]; gchar proto_tmp[32]; gint row; g_assert(n != NULL); gm_snprintf(proto_tmp, sizeof proto_tmp, "%d.%d", n->proto_major, n->proto_minor); titles[c_gnet_host] = host_addr_port_to_string(n->addr, n->port); titles[c_gnet_flags] = "..."; titles[c_gnet_user_agent] = n->vendor ? lazy_utf8_to_locale(n->vendor) : "..."; titles[c_gnet_loc] = iso3166_country_cc(n->country); titles[c_gnet_version] = proto_tmp; titles[c_gnet_connected] = "..."; titles[c_gnet_uptime] = "..."; titles[c_gnet_info] = "..."; clist_nodes = GTK_CLIST(gui_main_window_lookup("clist_nodes")); row = gtk_clist_append(clist_nodes, (gchar **) titles); /* override const */ gtk_clist_set_row_data(clist_nodes, row, deconstify_gpointer(nid_ref(n->node_id))); }
/** * Pretty-printing of node information for logs into the supplied buffers. * * IP address is followed by '*' if the contact's address/port was patched. * IP address is followed by '?' if the UDP message came from another IP * * A "zombie" node is a node retrieved from the persisted routing table that * is not alive. Normally, only alive hosts from which we get traffic are * added, but here we have an instance that is not alive -- a zombie. * * A "cached" node is a node coming from the k-closest root cache. * * A firewalled node is indicated by a trailing "fw" indication. * * @return the buffer where printing was done. */ const gchar * knode_to_string_buf(const knode_t *kn, char buf[], size_t len) { char host_buf[HOST_ADDR_PORT_BUFLEN]; char vc_buf[VENDOR_CODE_BUFLEN]; gchar kuid_buf[KUID_HEX_BUFLEN]; knode_check(kn); bin_to_hex_buf(kn->id, KUID_RAW_SIZE, kuid_buf, sizeof kuid_buf); host_addr_port_to_string_buf(kn->addr, kn->port, host_buf, sizeof host_buf); vendor_code_to_string_buf(kn->vcode.u32, vc_buf, sizeof vc_buf); gm_snprintf(buf, len, "%s%s%s (%s v%u.%u) [%s] \"%s\", ref=%d%s%s%s [%s]", host_buf, (kn->flags & KNODE_F_PCONTACT) ? "*" : "", (kn->flags & KNODE_F_FOREIGN_IP) ? "?" : "", vc_buf, kn->major, kn->minor, kuid_buf, knode_status_to_string(kn->status), kn->refcnt, (kn->status != KNODE_UNKNOWN && !(kn->flags & KNODE_F_ALIVE)) ? " zombie" : "", (kn->flags & KNODE_F_CACHED) ? " cached" : "", (kn->flags & KNODE_F_FIREWALLED) ? " fw" : "", compact_time(delta_time(tm_time(), kn->first_seen))); return buf; }
static void print_node_info(struct gnutella_shell *sh, const struct gnutella_node *n) { gnet_node_flags_t flags; time_delta_t up, con; char buf[1024]; char vendor_escaped[50]; char uptime_buf[8]; char contime_buf[8]; g_return_if_fail(sh); g_return_if_fail(n); if (!node_fill_flags(NODE_ID(n), &flags)) return; con = n->connect_date ? delta_time(tm_time(), n->connect_date) : 0; up = n->up_date ? delta_time(tm_time(), n->up_date) : 0; { const char *vendor; char *escaped; vendor = node_vendor(n); escaped = hex_escape(vendor, TRUE); clamp_strcpy(vendor_escaped, sizeof vendor_escaped, escaped); if (escaped != vendor) { HFREE_NULL(escaped); } } clamp_strcpy(uptime_buf, sizeof uptime_buf, up > 0 ? compact_time(up) : "?"); clamp_strcpy(contime_buf, sizeof contime_buf, con > 0 ? compact_time(con) : "?"); gm_snprintf(buf, sizeof buf, "%-21.45s %5.1u %s %2.2s %6.6s %6.6s %.50s", node_addr(n), (unsigned) n->gnet_port, node_flags_to_string(&flags), iso3166_country_cc(n->country), contime_buf, uptime_buf, vendor_escaped); shell_write(sh, buf); shell_write(sh, "\n"); /* Terminate line */ }
/** * Called when a row of the upload stats should be updated */ void upload_stats_gui_update_model(struct ul_stats *us) { GtkCList *clist = clist_ul_stats(); enum c_us i; int row; row = ul_stats_get_row(us); g_return_if_fail(row >= 0); for (i = 0; i < c_us_num; i++) { const char *text = NULL; char tmpstr[16]; switch (i) { case c_us_filename: case c_us_size: /* Never updated, only initialized */ continue; case c_us_attempts: text = uint64_to_string(us->attempts); break; case c_us_complete: text = uint64_to_string(us->complete); break; case c_us_norm: gm_snprintf(tmpstr, sizeof tmpstr, "%.3f", us->norm); text = tmpstr; break; case c_us_rtime: text = us->rtime ? timestamp_to_string(us->rtime) : ""; break; case c_us_dtime: text = us->dtime ? timestamp_to_string(us->dtime) : ""; break; case c_us_num: text = NULL; g_assert_not_reached(); } gtk_clist_set_text(clist, row, i, text); } /* FIXME: use auto-sort? */ if (0 == clist->freeze_count) { gtk_clist_sort(clist); clist_sync_rows(clist, on_clist_ul_stats_row_moved); } }
/** * Adds the X-Features header to a HTTP request. * * @param xfeatures structure holding the collected features * @param buf should point to the beginning of the header. * @param len no brief description. * @param rw the number of bytes that were already written. * * *rw is changed too *rw + bytes written */ void header_features_generate(xfeature_t xf, char *dst, size_t len, size_t *rw) { static const char hdr[] = "X-Features"; struct features *features; GList *cur; header_fmt_t *fmt; g_assert(len <= INT_MAX); g_assert(*rw <= INT_MAX); g_assert(len >= *rw); if (len - *rw < (sizeof(hdr) + sizeof(": \r\n") - 1)) return; features = features_get(xf); g_return_if_fail(features); if (g_list_first(features->list) == NULL) return; fmt = header_fmt_make(hdr, ", ", 0, len - *rw); for (cur = g_list_first(features->list); cur; cur = g_list_next(cur)) { struct header_x_feature *item = cur->data; char buf[50]; if (item->guard && !*item->guard) continue; if (item->guardfn && !(*item->guardfn)()) continue; gm_snprintf(buf, sizeof buf, "%s/%d.%d", item->name, item->major, item->minor); header_fmt_append_value(fmt, buf); } header_fmt_end(fmt); if (header_fmt_length(fmt) < len - *rw) { *rw += clamp_strncpy(&dst[*rw], len - *rw, header_fmt_string(fmt), header_fmt_length(fmt)); } header_fmt_free(&fmt); }
/** * Update the row with the given nodeinfo. If row is -1 the row number * is determined by the node_id contained in the gnet_node_info_t. */ static void nodes_gui_update_node_info(gnet_node_info_t *n, gint row) { GtkCList *clist = GTK_CLIST(gui_main_window_lookup("clist_nodes")); g_assert(n != NULL); if (row == -1) { row = gtk_clist_find_row_from_data(clist, deconstify_gpointer(n->node_id)); } if (row != -1) { gchar ver_buf[64]; gnet_node_status_t status; time_t now = tm_time(); if (guc_node_get_status(n->node_id, &status)) { gtk_clist_set_text(clist, row, c_gnet_user_agent, n->vendor ? lazy_utf8_to_locale(n->vendor) : "..."); gtk_clist_set_text(clist, row, c_gnet_loc, deconstify_gchar(iso3166_country_cc(n->country))); gm_snprintf(ver_buf, sizeof ver_buf, "%d.%d", n->proto_major, n->proto_minor); gtk_clist_set_text(clist, row, c_gnet_version, ver_buf); 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)); } } else { g_warning("%s: no matching row found", G_GNUC_PRETTY_FUNCTION); } }
static void search_stats_notify_whole(query_type_t type, const gchar *search, const host_addr_t unused_addr, guint16 unused_port) { word_vec_t wovec; gchar buf[1024]; (void) unused_addr; (void) unused_port; gm_snprintf(buf, sizeof buf, QUERY_SHA1 == type ? "urn:sha1:%s" : "[%s]", search); wovec.word = buf; wovec.len = strlen(wovec.word); wovec.amount = 1; search_stats_tally(&wovec); }
/** * Watcher callback, invoked when the file from which we read the bogus * addresses changed. */ static void bogons_changed(const char *filename, void *unused_udata) { FILE *f; char buf[80]; int count; (void) unused_udata; f = file_fopen(filename, "r"); if (f == NULL) return; bogons_close(); count = bogons_load(f); gm_snprintf(buf, sizeof(buf), "Reloaded %d bogus IP ranges.", count); gcu_statusbar_message(buf); }
/** * Dump field on specified file descriptor. */ static void hfield_dump(const header_field_t *h, FILE *out) { slist_iter_t *iter; gboolean first; header_field_check(h); g_assert(h->lines); fprintf(out, "%s: ", h->name); first = TRUE; iter = slist_iter_on_head(h->lines); for (/* NOTHING */; slist_iter_has_item(iter); slist_iter_next(iter)) { const char *s; if (!first) { first = FALSE; fputs(" ", out); /* Continuation line */ } s = slist_iter_current(iter); if (is_printable_iso8859_string(s)) { fputs(s, out); } else { char buf[80]; const char *p = s; int c; size_t len = strlen(s); gm_snprintf(buf, sizeof buf, "<%u non-printable byte%s>", (unsigned) len, 1 == len ? "" : "s"); fputs(buf, out); while ((c = *p++)) { if (is_ascii_print(c) || is_ascii_space(c)) fputc(c, out); else fputc('.', out); /* Less visual clutter than '?' */ } } fputc('\n', out); } slist_iter_free(&iter); }
/** * Watcher callback, invoked when the file from which we read the spam * changed. */ static void spam_changed(const char *filename, gpointer unused_udata) { FILE *f; (void) unused_udata; f = file_fopen(filename, "r"); if (f) { char buf[80]; gulong count; spam_close(); count = spam_load(f); fclose(f); gm_snprintf(buf, sizeof(buf), "Reloaded %lu spam items.", count); gcu_statusbar_message(buf); } }
/** * Displays assorted status information */ enum shell_reply shell_exec_status(struct gnutella_shell *sh, int argc, const char *argv[]) { const char *cur; const option_t options[] = { { "i", &cur }, }; int parsed; char buf[2048]; time_t now; shell_check(sh); g_assert(argv); g_assert(argc > 0); parsed = shell_options_parse(sh, argv, options, G_N_ELEMENTS(options)); if (parsed < 0) return REPLY_ERROR; argv += parsed; /* args[0] is first command argument */ argc -= parsed; /* counts only command arguments now */ now = tm_time(); /* Leading flags */ { char flags[47]; const char *fw; const char *fd; const char *pmp; const char *dht; /* * The flags are displayed as followed: * * UMP port mapping configured via UPnP * NMP port mapping configured via NAT-PMP * pmp port mapping available (UPnP or NAT-PMP), un-configured * CLK clock, GTKG expired * !FD or FD red or yellow bombs for fd shortage * STL upload stalls * gUL/yUL/rUL green, yellow or red upload early stalling levels * CPU cpu overloaded * MOV file moving * SHA SHA-1 rebuilding or verifying * TTH TTH rebuilding or verifying * LIB library rescan * :FW or FW indicates whether hole punching is possible * udp or UDP indicates UDP firewalling (lowercased for hole punching) * TCP indicates TCP-firewalled * - the happy face: no firewall * sDH/lDH/bDH seeded, own KUID looking or bootstrapping DHT * A or P active or passive DHT mode * UP or LF ultrapeer or leaf mode */ pmp = (GNET_PROPERTY(upnp_possible) || GNET_PROPERTY(natpmp_possible)) ? "pmp " : empty; if ( (GNET_PROPERTY(enable_upnp) || GNET_PROPERTY(enable_natpmp)) && GNET_PROPERTY(port_mapping_successful) ) { pmp = GNET_PROPERTY(enable_natpmp) ? "NMP " : "UMP "; } if (dht_enabled()) { dht = empty; switch ((enum dht_bootsteps) GNET_PROPERTY(dht_boot_status)) { case DHT_BOOT_NONE: case DHT_BOOT_SHUTDOWN: break; case DHT_BOOT_SEEDED: dht = "sDH "; break; case DHT_BOOT_OWN: dht = "lDH "; break; case DHT_BOOT_COMPLETING: dht = "bDH "; break; case DHT_BOOT_COMPLETED: dht = dht_is_active() ? "A " : "P "; break; case DHT_BOOT_MAX_VALUE: g_assert_not_reached(); } } else { dht = empty; } if (GNET_PROPERTY(is_firewalled) && GNET_PROPERTY(is_udp_firewalled)) { fw = GNET_PROPERTY(recv_solicited_udp) ? ":FW " : "FW "; } else if (GNET_PROPERTY(is_firewalled)) { fw = "TCP "; } else if (GNET_PROPERTY(is_udp_firewalled)) { fw = GNET_PROPERTY(recv_solicited_udp) ? "udp " : "UDP "; } else { fw = "- "; } if (GNET_PROPERTY(file_descriptor_runout)) { fd = "!FD "; } else if (GNET_PROPERTY(file_descriptor_shortage)) { fd = "FD "; } else { fd = empty; } gm_snprintf(flags, sizeof flags, "<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>", pmp, GNET_PROPERTY(download_queue_frozen) ? "DFZ " : empty, GNET_PROPERTY(ancient_version) ? "CLK " : empty, fd, GNET_PROPERTY(uploads_stalling) ? "STL " : empty, GNET_PROPERTY(uploads_bw_ignore_stolen) ? "gUL " : empty, GNET_PROPERTY(uploads_bw_uniform) ? "yUL " : empty, GNET_PROPERTY(uploads_bw_no_stealing) ? "rUL " : empty, GNET_PROPERTY(overloaded_cpu) ? "CPU " : empty, GNET_PROPERTY(file_moving) ? "MOV " : empty, (GNET_PROPERTY(sha1_rebuilding) || GNET_PROPERTY(sha1_verifying)) ? "SHA " : empty, (GNET_PROPERTY(tth_rebuilding) || GNET_PROPERTY(tth_verifying)) ? "TTH " : empty, GNET_PROPERTY(library_rebuilding) ? "LIB " : empty, fw, dht, settings_is_ultra() ? "UP" : "LF"); gm_snprintf(buf, sizeof buf, "+%s+\n" "| %-18s%51s |\n" "|%s|\n", dashes, "Status", flags, equals); shell_write(sh, buf); } /* General status */ { const char *blackout; short_string_t leaf_switch; short_string_t ultra_check; leaf_switch = timestamp_get_string( GNET_PROPERTY(node_last_ultra_leaf_switch)); ultra_check = timestamp_get_string( GNET_PROPERTY(node_last_ultra_check)); if (GNET_PROPERTY(is_firewalled) && GNET_PROPERTY(is_udp_firewalled)) { blackout = GNET_PROPERTY(recv_solicited_udp) ? "TCP,udp" : "TCP,UDP"; } else if (GNET_PROPERTY(is_firewalled)) { blackout = "TCP"; } else if (GNET_PROPERTY(is_udp_firewalled)) { blackout = GNET_PROPERTY(recv_solicited_udp) ? "udp" : "UDP"; } else { blackout = "None"; } gm_snprintf(buf, sizeof buf, "| Mode: %-9s Last Switch: %-19s%2s|\n" "| Uptime: %-9s Last Check: %-19s%2s|\n" "| Port: %-9u Blackout: %-7s%14s|\n" "|%s|\n", GNET_PROPERTY(online_mode) ? node_peermode_to_string(GNET_PROPERTY(current_peermode)) : "offline", GNET_PROPERTY(node_last_ultra_leaf_switch) ? leaf_switch.str : "never", space, short_time(delta_time(now, GNET_PROPERTY(start_stamp))), GNET_PROPERTY(node_last_ultra_check) ? ultra_check.str : "never", space, socket_listen_port(), blackout, space, equals); shell_write(sh, buf); } /* IPv4 info */ switch (GNET_PROPERTY(network_protocol)) { case NET_USE_BOTH: case NET_USE_IPV4: gm_snprintf(buf, sizeof buf, "| IPv4: %-44s Since: %-12s|\n", host_addr_to_string(listen_addr()), short_time(delta_time(now, GNET_PROPERTY(current_ip_stamp)))); shell_write(sh, buf); } /* IPv6 info */ switch (GNET_PROPERTY(network_protocol)) { case NET_USE_BOTH: gm_snprintf(buf, sizeof buf, "|%s|\n", dashes); shell_write(sh, buf); /* FALL THROUGH */ case NET_USE_IPV6: gm_snprintf(buf, sizeof buf, "| IPv6: %-44s Since: %-12s|\n", host_addr_to_string(listen_addr6()), short_time(delta_time(now, GNET_PROPERTY(current_ip6_stamp)))); shell_write(sh, buf); } /* Node counts */ gm_snprintf(buf, sizeof buf, "|%s|\n" "| Peers: %-7u Ultra %4u/%-7u Leaf %4u/%-6u Legacy %4u/%-4u |\n" "| Downloads %4u/%-4u Uploads %4u/%-7u Browse %4u/%-4u |\n" "|%s|\n", equals, GNET_PROPERTY(node_ultra_count) + GNET_PROPERTY(node_leaf_count) + GNET_PROPERTY(node_normal_count), GNET_PROPERTY(node_ultra_count), settings_is_ultra() ? GNET_PROPERTY(max_connections) : GNET_PROPERTY(max_ultrapeers), GNET_PROPERTY(node_leaf_count), GNET_PROPERTY(max_leaves), GNET_PROPERTY(node_normal_count), GNET_PROPERTY(normal_connections), GNET_PROPERTY(dl_active_count), GNET_PROPERTY(dl_running_count), GNET_PROPERTY(ul_running), GNET_PROPERTY(ul_registered), GNET_PROPERTY(html_browse_served) + GNET_PROPERTY(qhits_browse_served), GNET_PROPERTY(html_browse_count) + GNET_PROPERTY(qhits_browse_count), equals); shell_write(sh, buf); /* Bandwidths */ { const bool metric = GNET_PROPERTY(display_metric_units); short_string_t gnet_in, http_in, leaf_in, gnet_out, http_out, leaf_out; short_string_t dht_in, dht_out; gnet_bw_stats_t bw_stats, bw2_stats; const char *bwtype = cur ? "(cur)" : "(avg)"; gnet_get_bw_stats(BW_GNET_IN, &bw_stats); gnet_get_bw_stats(BW_GNET_UDP_IN, &bw2_stats); gnet_in = short_rate_get_string( cur ? bw_stats.current + bw2_stats.current : bw_stats.average + bw2_stats.average, metric); gnet_get_bw_stats(BW_GNET_OUT, &bw_stats); gnet_get_bw_stats(BW_GNET_UDP_OUT, &bw2_stats); gnet_out = short_rate_get_string( cur ? bw_stats.current + bw2_stats.current : bw_stats.average + bw2_stats.average, metric); gnet_get_bw_stats(BW_HTTP_IN, &bw_stats); http_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_HTTP_OUT, &bw_stats); http_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_LEAF_IN, &bw_stats); leaf_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_LEAF_OUT, &bw_stats); leaf_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_DHT_IN, &bw_stats); dht_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_DHT_OUT, &bw_stats); dht_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gm_snprintf(buf, sizeof buf, "| %-70s|\n" "|%71s|\n" "| %5s In: %13s %13s %13s %13s |\n" "| %5s Out: %13s %13s %13s %13s |\n", "Bandwidth:" " Gnutella Leaf HTTP DHT", dashes, bwtype, gnet_in.str, leaf_in.str, http_in.str, dht_in.str, bwtype, gnet_out.str, leaf_out.str, http_out.str, dht_out.str); shell_write(sh, buf); } { char line[128]; bool metric = GNET_PROPERTY(display_metric_units); gm_snprintf(buf, sizeof buf, "|%s|\n", equals); shell_write(sh, buf); concat_strings(line, sizeof line, "Shares ", uint64_to_string(shared_files_scanned()), " file", shared_files_scanned() == 1 ? "" : "s", " ", short_kb_size(shared_kbytes_scanned(), metric), " total", (void *) 0); gm_snprintf(buf, sizeof buf, "| %-35s Up: %-11s Down: %-11s |\n", line, short_byte_size(GNET_PROPERTY(ul_byte_count), metric), short_byte_size2(GNET_PROPERTY(dl_byte_count), metric)); shell_write(sh, buf); gm_snprintf(buf, sizeof buf, "+%s+\n", dashes); shell_write(sh, buf); } return REPLY_READY; }
/** * Launch UPnP control request. * * The argv[] vector (with argc entries) contains the arguments and their * values to send to the remote UPnP device. * * If a structured reply is expected (and not just a returned status code), * a launch_cb callback must be provided to process the arguments returned * by the control request and populate a structure that will be passed to the * user callback to propagate the result of the control request. * * @param usd the service to contact * @param action the action to request * @param argv the argument list for the request * @param argc amount of arguments in argv[] * @param cb user-callback when action is completed * @param cb_arg additional callback argument * @param launch_cb internal launch callback invoked on SOAP reply * * @return UPnP request handle if the SOAP RPC was initiated, NULL otherwise * (in which case callbacks will never be called). */ static upnp_ctrl_t * upnp_ctrl_launch(const upnp_service_t *usd, const char *action, nv_pair_t **argv, size_t argc, upnp_ctrl_cb_t cb, void *cb_arg, upnp_ctrl_launch_cb_t launch_cb) { upnp_ctrl_t *ucd; xnode_t *root; size_t i; soap_rpc_t *sr; g_assert(usd != NULL); g_assert(action != NULL); g_assert(0 == argc || argv != NULL); WALLOC0(ucd); ucd->magic = UPNP_CTRL_MAGIC; ucd->lcb = launch_cb; ucd->cb = cb; ucd->cb_arg = cb_arg; /* * The root element of the UPnP request. * * Its serialized form looks like this: * * <u:action xmlns:u="urn:schemas-upnp-org:service:serviceType:v"> * <arg1>in value1</arg1> * <arg2>in value2</arg2> * : : : : * <argn>in valuen</argn> * </u:action> * * The "u" prefix is arbitrary but it is the one used in all examples * presented in the UPnP architecture, and naive implementations within * devices could choke on anything else. */ { char ns[256]; gm_snprintf(ns, sizeof ns, "%s%s:%u", UPNP_NS_BASE, upnp_service_type_to_string(upnp_service_type(usd)), upnp_service_version(usd)); root = xnode_new_element(NULL, ns, action); xnode_add_namespace(root, UPNP_PREFIX, ns); } /* * Attach each argument to the root. */ for (i = 0; i < argc; i++) { nv_pair_t *nv = argv[i]; xnode_t *xargs; xargs = xnode_new_element(root, NULL, nv_pair_name(nv)); xnode_new_text(xargs, nv_pair_value_str(nv), FALSE); } /* * Launch the SOAP RPC. * * We force "s" as the SOAP prefix. It shouldn't matter at all, but * since the UPnP architecture documents its examples with "s", naive * implementations in devices could choke on anything else. * * Likewise, since the UPnP architecture document uses all-caps HTTP header * names, we can expect that some implementations within devices will * not properly understand headers spelt with traditional mixed-cased, * although it mentions that headers are case-insensitive names. Hence, * force all-caps header names. * * If the SOAP RPC cannot be launched (payload too large), the XML tree * built above was freed anyway. */ { char action_uri[256]; guint32 options = SOAP_RPC_O_MAN_RETRY | SOAP_RPC_O_ALL_CAPS; /* * Grab our local IP address if it is unknown so far. */ if (host_addr_net(upnp_get_local_addr()) == NET_TYPE_NONE) options |= SOAP_RPC_O_LOCAL_ADDR; gm_snprintf(action_uri, sizeof action_uri, "%s#%s", xnode_element_ns(root), action); ucd->action = atom_str_get(action_uri); sr = soap_rpc(upnp_service_control_url(usd), action_uri, UPNP_REPLY_MAXSIZE, options, root, UPNP_SOAP_PREFIX, upnp_ctrl_soap_reply, upnp_ctrl_soap_error, ucd); } /* * We no longer need the arguments. */ for (i = 0; i < argc; i++) { nv_pair_free_null(&argv[i]); } /* * Cleanup if we were not able to launch the request because the * serialized XML payload is too large. */ if (NULL == sr) { if (GNET_PROPERTY(upnp_debug)) { g_warning("UPNP SOAP RPC \"%s\" to \"%s\" not launched: " "payload is too large", action, upnp_service_control_url(usd)); } upnp_ctrl_free(ucd); return NULL; } ucd->sr = sr; /* So that we may cancel it if needed */ return ucd; }
/** * @return a pointer to a static buffer containing a string which * describes the current status of the upload. */ const gchar * uploads_gui_status_str(const gnet_upload_status_t *u, const upload_row_data_t *data) { static gchar tmpstr[256]; if (u->pos < data->range_start) return _("No output yet..."); /* Never wrote anything yet */ switch (u->status) { case GTA_UL_PUSH_RECEIVED: return _("Got push, connecting back..."); case GTA_UL_COMPLETE: { time_delta_t d = delta_time(data->last_update, data->start_date); filesize_t requested = data->range_end - data->range_start + 1; size_t rw; rw = gm_snprintf(tmpstr, sizeof(tmpstr), "%s (%s) %s %s#%u", _("Completed"), d > 0 ? short_rate(requested / d, show_metric_units()) : _("< 1s"), d > 0 ? short_time(d) : "", u->parq_quick ? _("(quick) ") : "", u->reqnum); if (u->error_count) rw += gm_snprintf(&tmpstr[rw], sizeof(tmpstr)-rw, _(" E=%u"), u->error_count); } break; case GTA_UL_SENDING: { /* Time Remaining at the current rate, in seconds */ filesize_t tr = (data->range_end + 1 - u->pos) / MAX(1, u->avg_bps); gdouble p = uploads_gui_progress(u, data); time_t now = tm_time(); gboolean stalled = delta_time(now, data->last_update) > IO_STALLED; gchar pbuf[32]; size_t rw; gm_snprintf(pbuf, sizeof pbuf, "%5.02f%% ", p * 100.0); rw = gm_snprintf(tmpstr, sizeof tmpstr, _("%s(%s) TR: %s %s#%u"), p > 1.0 ? pbuf : "", stalled ? _("stalled") : short_rate(u->bps, show_metric_units()), short_time(tr), u->parq_quick ? _("(quick) ") : "", u->reqnum); if (u->error_count) rw += gm_snprintf(&tmpstr[rw], sizeof(tmpstr)-rw, _(" E=%u"), u->error_count); } break; case GTA_UL_HEADERS: return _("Waiting for headers..."); case GTA_UL_EXPECTING: if (u->error_count) gm_snprintf(tmpstr, sizeof(tmpstr), _("%s %s#%u E=%u"), _("Waiting for further request..."), u->parq_quick ? _("(quick) ") : "", u->reqnum, u->error_count); else gm_snprintf(tmpstr, sizeof(tmpstr), "%s %s#%u", _("Waiting for further request..."), u->parq_quick ? _("(quick) ") : "", u->reqnum); break; case GTA_UL_WAITING: return _("Reading follow-up request..."); case GTA_UL_ABORTED: return _("Transmission aborted"); case GTA_UL_CLOSED: return _("Transmission complete"); case GTA_UL_QUEUED: /* Actively queued */ { guint32 max_up, cur_up; gboolean queued; guint available = 0; gchar tbuf[64]; size_t rw; gnet_prop_get_guint32_val(PROP_MAX_UPLOADS, &max_up); gnet_prop_get_guint32_val(PROP_UL_RUNNING, &cur_up); if (cur_up < max_up) available = max_up - cur_up; /* * We'll flag as "Waiting" instead of "Queued" uploads * that are actively queued and whose position is low * enough to possibly get scheduled at the next request, * given the amount of free slots. * --RAM, 2007-08-21 */ queued = u->parq_position > available; if (u->parq_retry > 0) { gm_snprintf(tbuf, sizeof tbuf, " %s,", short_time(u->parq_retry)); } else { tbuf[0] = '\0'; } rw = gm_snprintf(tmpstr, sizeof tmpstr, _("%s [%d] (slot %d/%d)%s %s %s"), u->parq_frozen ? _("Frozen") : queued ? _("Queued") : _("Waiting"), u->parq_queue_no, u->parq_position, u->parq_size, tbuf, _("lifetime:"), short_time(u->parq_lifetime)); if (u->error_count) rw += gm_snprintf(&tmpstr[rw], sizeof(tmpstr)-rw, _(" E=%u"), u->error_count); } break; case GTA_UL_QUEUE: /* * PARQ wants to inform a client that action from the client its side * is wanted. So it is trying to connect back. * -- JA, 15/04/2003 */ return _("Sending QUEUE, connecting back..."); case GTA_UL_QUEUE_WAITING: /* * PARQ made a connect back because some action from the client is * wanted. The connection is established and now waiting for some action * -- JA, 15/04/2003 */ return _("Sent QUEUE, waiting for headers..."); } return tmpstr; }
/** * Build our own HTTP request. * * See http_async_build_post_request() for the model and details about * the various parameters. * * @return length of generated request. */ static size_t soap_build_request(const http_async_t *ha, char *buf, size_t len, const char *verb, const char *path, const char *content_type, size_t content_len) { soap_rpc_t *sr = http_async_get_opaque(ha); size_t rw; const char *fixed_header; soap_rpc_check(sr); g_assert(len <= INT_MAX); if (sr->options & SOAP_RPC_O_MAN_FORCE) { sr->mandatory = TRUE; } else if ((sr->options & SOAP_RPC_O_MAN_RETRY) && sr->regular) { sr->mandatory = TRUE; } else { sr->mandatory = FALSE; sr->regular = TRUE; } if (sr->options & SOAP_RPC_O_ALL_CAPS) { fixed_header = "ACCEPT-ENCODING: deflate\r\n" "CONNECTION: close\r\n" "CACHE-CONTROL: no-cache\r\n" "PRAGMA: no-cache\r\n"; } else { fixed_header = "Accept-Encoding: deflate\r\n" "Connection: close\r\n" "Cache-Control: no-cache\r\n" "Pragma: no-cache\r\n"; } if (sr->mandatory) { if (sr->options & SOAP_RPC_O_ALL_CAPS) { rw = gm_snprintf(buf, len, "M-%s %s HTTP/1.1\r\n" "HOST: %s\r\n" "USER-AGENT: %s\r\n" "CONTENT-TYPE: %s\r\n" "CONTENT-LENGTH: %s\r\n" "%s" /* Fixed header part */ "MAN: \"%s\"; ns=01\r\n" "01-SOAPACTION: \"%s\"\r\n" "\r\n", verb, path, http_async_remote_host_port(ha), version_string, content_type, size_t_to_string(content_len), fixed_header, SOAP_NAMESPACE, sr->action); } else { rw = gm_snprintf(buf, len, "M-%s %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" "Content-Type: %s\r\n" "Content-Length: %s\r\n" "%s" /* Fixed header part */ "Man: \"%s\"; ns=01\r\n" "01-SOAPAction: \"%s\"\r\n" "\r\n", verb, path, http_async_remote_host_port(ha), version_string, content_type, size_t_to_string(content_len), fixed_header, SOAP_NAMESPACE, sr->action); } } else { if (sr->options & SOAP_RPC_O_ALL_CAPS) { rw = gm_snprintf(buf, len, "%s %s HTTP/1.1\r\n" "HOST: %s\r\n" "USER-AGENT: %s\r\n" "CONTENT-TYPE: %s\r\n" "CONTENT-LENGTH: %s\r\n" "%s" /* Fixed header part */ "SOAPACTION: \"%s\"\r\n" "\r\n", verb, path, http_async_remote_host_port(ha), version_string, content_type, size_t_to_string(content_len), fixed_header, sr->action); } else { rw = gm_snprintf(buf, len, "%s %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" "Content-Type: %s\r\n" "Content-Length: %s\r\n" "%s" /* Fixed header part */ "SOAPAction: \"%s\"\r\n" "\r\n", verb, path, http_async_remote_host_port(ha), version_string, content_type, size_t_to_string(content_len), fixed_header, sr->action); } } return rw; }
static void html_output_tag(struct html_output *output, const struct array *tag) #if GTK_CHECK_VERSION(2,0,0) { static struct { gboolean initialized; short_string_t centre_line, nbsp, bullet, soft_hyphen, em_dash; short_string_t list_item_prefix; } special; struct html_context *ctx; const gchar *style, *text, *attr; enum html_tag id; gboolean closing; GtkTextBuffer *buffer; if (!special.initialized) { special.initialized = TRUE; special.bullet = utf8_char(0x2022); special.centre_line = utf8_char(0xFE4E); special.soft_hyphen = utf8_char(0x00AD); special.nbsp = utf8_char(0x00A0); special.em_dash = utf8_char(0x2014); concat_strings(special.list_item_prefix.str, sizeof special.list_item_prefix.str, " ", special.bullet.str, " ", (void *) 0); } style = NULL; text = NULL; attr = NULL; closing = html_tag_is_closing(tag); ctx = html_output_get_udata(output); id = html_parse_tag(tag); buffer = gtk_text_view_get_buffer(ctx->html_view->widget); switch (id) { case HTML_TAG_BODY: style = STYLE_TAG_WORD_WRAP; break; case HTML_TAG_A: if (closing) { if (ctx->start[id] && ctx->href) { GtkTextIter start, end; GtkTextTag *anchor; anchor = gtk_text_buffer_create_tag(buffer, NULL, (void *) 0); g_object_set_data(G_OBJECT(anchor), "href", deconstify_gchar(ctx->href)); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, anchor, &start, &end); style = get_style_for_href(ctx->href); ctx->href = NULL; } } else { struct array value; value = html_get_attribute(tag, HTML_ATTR_HREF); if (value.data && value.size > 0) { GtkTextIter iter; ctx->href = g_strndup(value.data, value.size); ctx->html_view->to_free = g_slist_prepend( ctx->html_view->to_free, deconstify_gchar(ctx->href)); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); g_object_set_data(G_OBJECT(ctx->start[id]), "href", deconstify_gchar(ctx->href)); } value = html_get_attribute(tag, HTML_ATTR_NAME); if (value.data && value.size > 0) { GtkTextTagTable *table; gchar name[256]; size_t n; n = sizeof name - 2; n = MIN(value.size, n); name[0] = '#'; memcpy(&name[1], value.data, n); name[n + 1] = '\0'; table = gtk_text_buffer_get_tag_table(buffer); if (NULL == gtk_text_tag_table_lookup(table, name)) { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, name, &iter, TRUE); } } } break; case HTML_TAG_B: case HTML_TAG_STRONG: case HTML_TAG_THEAD: style = STYLE_TAG_BOLD; break; case HTML_TAG_TH: if (closing) text = "\t"; break; case HTML_TAG_EM: style = STYLE_TAG_UNDERLINE; break; case HTML_TAG_I: case HTML_TAG_Q: style = STYLE_TAG_ITALIC; break; case HTML_TAG_IMG: if (!closing) { struct array value; static gchar alt[1024]; value = html_get_attribute(tag, HTML_ATTR_ALT); if (value.data) { gm_snprintf(alt, sizeof alt, "\n[image alt=\"%.*s\"]\n", (int)value.size, value.data); text = alt; } value = html_get_attribute(tag, HTML_ATTR_SRC); if (value.data) { GdkPixbuf *pixbuf; gchar *filename; GtkTextIter iter; filename = h_strndup(value.data, value.size); pixbuf = gdk_pixbuf_new_from_file(filename, NULL); if (pixbuf) { gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf); } else { static gchar msg[1024]; gm_snprintf(msg, sizeof msg, "\n[Image not found (\"%s\")]\n", filename); text = msg; } HFREE_NULL(filename); } if (!text) { text = "\n[image]\n"; } } attr = STYLE_TAG_BOLD; break; case HTML_TAG_TD: if (closing) text = "\t"; break; case HTML_TAG_P: case HTML_TAG_DIV: text = closing ? "\n\n" : special.soft_hyphen.str; break; case HTML_TAG_DL: case HTML_TAG_TABLE: case HTML_TAG_TR: case HTML_TAG_UL: case HTML_TAG_OL: case HTML_TAG_BR: text = "\n"; break; case HTML_TAG_DT: case HTML_TAG_LI: if (closing) { GtkTextIter start, end; GtkTextTag *margin; PangoLayout *pl; gint width; pl = pango_layout_new(gtk_widget_get_pango_context( GTK_WIDGET(ctx->html_view->widget))); pango_layout_set_text(pl, special.list_item_prefix.str, -1); pango_layout_get_pixel_size(pl, &width, NULL); g_object_unref(G_OBJECT(pl)); margin = gtk_text_buffer_create_tag(buffer, NULL, "left-margin", width * 2, "left-margin-set", TRUE, (void *) 0); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, margin, &start, &end); } else { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, "\n", (-1)); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, special.list_item_prefix.str, (-1), STYLE_TAG_BOLD, (void *) 0); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } break; case HTML_TAG_CODE: case HTML_TAG_KBD: case HTML_TAG_PRE: case HTML_TAG_TT: style = STYLE_TAG_MONOSPACE; break; case HTML_TAG_H1: style = STYLE_TAG_HEADING_1; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H2: style = STYLE_TAG_HEADING_2; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H3: style = STYLE_TAG_HEADING_3; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H4: case HTML_TAG_H5: case HTML_TAG_H6: style = STYLE_TAG_HEADING_4; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_TITLE: if (closing) { if (ctx->title) { GtkWidget *window; window = gtk_widget_get_toplevel( GTK_WIDGET(ctx->html_view->widget)); gtk_window_set_title(GTK_WINDOW(window), str_2c(ctx->title)); str_destroy_null(&ctx->title); } } else { ctx->title = str_new(0); } break; case HTML_TAG_HR: { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "\n \n", (-1), STYLE_TAG_CENTER, STYLE_TAG_UNDERLINE, (void *) 0); } text = "\n"; break; case HTML_TAG_COMMENT: #if 0 { GtkTextIter iter; /* Comments can be made visible this way */ ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, tag->data, tag->size, STYLE_TAG_ITALIC, (void *) 0); } closing = TRUE; text = "\n"; #endif break; case HTML_TAG_HTML: if (closing) { if (ctx->lang && ctx->start[id]) { GtkTextIter start, end; GtkTextTag *lang; lang = gtk_text_buffer_create_tag(buffer, NULL, "language", ctx->lang, "language-set", TRUE, (void *) 0); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, lang, &start, &end); ctx->lang = NULL; } } else { struct array value; value = html_get_attribute(tag, HTML_ATTR_LANG); if (value.data && value.size > 0) { GtkTextIter iter; ctx->lang = g_strndup(value.data, value.size); ctx->html_view->to_free = g_slist_prepend( ctx->html_view->to_free, deconstify_gchar(ctx->lang)); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } } case HTML_TAG_HEAD: case HTML_TAG_META: case HTML_TAG_SPAN: case HTML_TAG_COL: case HTML_TAG_DD: case HTML_TAG_TBODY: case HTML_TAG_DOCTYPE: case HTML_TAG_UNKNOWN: break; case NUM_HTML_TAG: g_assert_not_reached(); } if (style) { if (closing) { if (ctx->start[id]) { GtkTextIter start, end; gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag_by_name(buffer, style, &start, &end); ctx->start[id] = NULL; } } else { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } } if (text) { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, text, (-1), attr, (void *) 0); } }