Example #1
0
void
hsep_timer(time_t now)
{
	const GSList *sl;
	bool scanning_shared;
	static time_t last_sent = 0;

	/* update number of shared files and KiB */

	gnet_prop_get_boolean_val(PROP_LIBRARY_REBUILDING, &scanning_shared);

	if (!scanning_shared) {
		if (upload_is_enabled())
			hsep_notify_shared(shared_files_scanned(), shared_kbytes_scanned());
		else
			hsep_notify_shared(0UL, 0UL);
	}

	for (sl = node_all_nodes(); sl; sl = g_slist_next(sl)) {
		struct gnutella_node *n = sl->data;
		int diff;

		/* only consider established connections here */
		if (!NODE_IS_ESTABLISHED(n))
			continue;

		if (!(n->attrs & NODE_A_CAN_HSEP))
			continue;

		/* check how many seconds ago the last message was sent */
		diff = n->hsep->random_skew + delta_time(now, n->hsep->last_sent);

		/* the -900 is used to react to changes in system time */
		if (diff >= HSEP_MSG_INTERVAL || diff < -900)
			hsep_send_msg(n, now);
	}

	/*
	 * Quick'n dirty hack to update the horizon stats in the
	 * statusbar at least once every 3 seconds.
	 *
	 * TODO: remove this and implement it properly in the
	 * statusbar code.
	 */

	if (delta_time(now, last_sent) >= 3) {
		hsep_fire_global_table_changed(now);
		last_sent = now;
	}
}
Example #2
0
/**
 * Build a Local Node Info message.
 *
 * @return a /LNI message.
 */
pmsg_t *
g2_build_lni(void)
{
	g2_tree_t *t;
	pmsg_t *mb;

	t = g2_tree_alloc_empty(G2_NAME(LNI));

	/* LS -- library statistics */

	{
		uint32 files, kbytes;
		char payload[8];
		void *p = payload;
		g2_tree_t *c;

		files  = MIN(shared_files_scanned(), ~((uint32) 0U));
		kbytes = MIN(shared_kbytes_scanned(), ~((uint32) 0U));

		p = poke_le32(p, files);
		p = poke_le32(p, kbytes);

		c = g2_tree_alloc_copy("LS", payload, sizeof payload);
		g2_tree_add_child(t, c);
	}

	g2_build_add_firewalled(t);		/* FW -- whether servent is firewalled */
	g2_build_add_uptime(t);			/* UP -- servent uptime */
	g2_build_add_vendor(t);			/* V  -- vendor code */
	g2_build_add_guid(t);			/* GU -- the GUID of this node */
	g2_build_add_node_address(t);	/* NA -- the IP:port of this node */
	g2_build_add_tls(t);			/* TLS -- whether TLS is supported */

	mb = g2_build_pmsg(t);
	g2_tree_free_null(&t);

	return mb;
}
Example #3
0
/**
 * 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>&nbsp;[",
							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>"
							"&nbsp;[",
							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);
}
Example #4
0
/**
 * 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;
}
Example #5
0
guint64
guc_shared_kbytes_scanned(void)
{
    return shared_kbytes_scanned();
}