Exemple #1
0
/**
 * Add a new host to our pong reserve, although the information here
 * does not come from a pong but from a Query Hit packet, hence the port
 * may be unsuitable for Gnet connections.
 */
void
host_add_semi_pong(const host_addr_t addr, guint16 port)
{
	g_assert(host_low_on_pongs);	/* Only used when low on pongs */

    hcache_add_caught(HOST_ANY, addr, port, "semi-pong");
}
Exemple #2
0
/**
 * Add a new host to our pong reserve.
 *
 * When `connect' is true, attempt to connect if we are low in Gnet links.
 */
void
host_add(const host_addr_t addr, guint16 port, gboolean do_connect)
{
	if (!do_connect || !hcache_add_caught(HOST_ANY, addr, port, "pong"))
		return;

	/*
	 * If we are under the number of connections wanted, we add this host
	 * to the connection list.
	 */


	if (node_keep_missing() > 0)
		node_add(addr, port, 0);
	else if (
		GNET_PROPERTY(use_netmasks) &&
		host_is_nearby(addr) &&
		node_remove_worst(TRUE)
	) {
		/*
		 * If we are above the max connections, delete a non-nearby
		 * connection before adding this better one
		 */
		node_add(addr, port, 0);
	}
}
Exemple #3
0
/**
 * Tree message iterator to handle "NH" nodes and extract their IP:port.
 */
static void
g2_node_extract_nh(void *data, void *udata)
{
	const g2_tree_t *t = data;

	(void) udata;

	if (0 == strcmp("NH", g2_tree_name(t))) {
		host_addr_t addr;
		uint16 port;

		if (
			g2_node_parse_address(t, &addr, &port) &&
			host_is_valid(addr, port)
		) {
			hcache_add_caught(HOST_G2HUB, addr, port, "/KHL/NH");
		}
	}
}
Exemple #4
0
/**
 * Called from parse_dispatch_lines() for each complete line of output.
 *
 * @return FALSE to stop processing of any remaining data.
 */
static bool
ghc_host_line(struct parse_context *ctx, const char *buf, size_t len)
{
	if (GNET_PROPERTY(bootstrap_debug) > 2)
		g_debug("BOOT GHC host line #%u (%zu bytes): %s",
			ctx->processed + 1, len, buf);

	if (len) {
		host_addr_t addr;
		uint16 port;

		if (string_to_host_addr_port(buf, NULL, &addr, &port)) {
			ctx->processed++;
			hcache_add_caught(HOST_ULTRA, addr, port, "GHC");

			if (GNET_PROPERTY(bootstrap_debug) > 1)
				g_debug("BOOT collected %s from GHC %s",
					host_addr_to_string(addr), http_async_url(ctx->handle));
		}
	}

	return TRUE;
}
Exemple #5
0
/**
 * Called when a pong with an "IPP" extension was received.
 */
void
uhc_ipp_extract(gnutella_node_t *n, const char *payload, int paylen,
	enum net_type type)
{
	int i, cnt;
	int len = NET_TYPE_IPV6 == type ? 18 : 6;
	const void *p;

	g_assert(0 == paylen % len);

	cnt = paylen / len;

	if (GNET_PROPERTY(bootstrap_debug))
		g_debug("extracting %d host%s in UDP IPP pong #%s from %s",
			cnt, plural(cnt),
			guid_hex_str(gnutella_header_get_muid(&n->header)), node_addr(n));

	for (i = 0, p = payload; i < cnt; i++, p = const_ptr_add_offset(p, len)) {
		host_addr_t ha;
		uint16 port;

		host_ip_port_peek(p, type, &ha, &port);
		hcache_add_caught(HOST_ULTRA, ha, port, "UDP-HC");

		if (GNET_PROPERTY(bootstrap_debug) > 2)
			g_debug("BOOT collected %s from UDP IPP pong from %s",
				host_addr_port_to_string(ha, port), node_addr(n));
	}

	if (!uhc_connecting)
		return;

	/*
	 * Check whether this was a reply from our request.
	 *
	 * The reply could come well after we decided it timed out and picked
	 * another UDP host cache, which ended-up replying, so we must really
	 * check whether we're still in a probing cycle.
	 */

	if (!guid_eq(&uhc_ctx.muid, gnutella_header_get_muid(&n->header)))
		return;

	if (GNET_PROPERTY(bootstrap_debug)) {
		g_debug("BOOT UDP cache \"%s\" replied: got %d host%s from %s",
			uhc_ctx.host, cnt, plural(cnt), node_addr(n));
	}

	/*
	 * Terminate the probing cycle if we got hosts.
	 */

	if (cnt > 0) {
		char msg[256];

		cq_cancel(&uhc_ctx.timeout_ev);
		uhc_connecting = FALSE;

		str_bprintf(msg, sizeof(msg),
			NG_("Got %d host from UDP host cache %s",
				"Got %d hosts from UDP host cache %s",
				cnt),
			cnt, uhc_ctx.host);

		gcu_statusbar_message(msg);
	} else {
		uhc_try_next();
	}
}
Exemple #6
0
/**
 * Periodic host heartbeat timer.
 */
void
host_timer(void)
{
    guint count;
	int missing;
	host_addr_t addr;
	guint16 port;
	host_type_t htype;
	guint max_nodes;
	gboolean empty_cache = FALSE;

	if (in_shutdown || !GNET_PROPERTY(online_mode))
		return;

	max_nodes = settings_is_leaf() ?
		GNET_PROPERTY(max_ultrapeers) : GNET_PROPERTY(max_connections);
	count = node_count();			/* Established + connecting */
	missing = node_keep_missing();

	if (GNET_PROPERTY(host_debug) > 1)
		g_debug("host_timer - count %u, missing %u", count, missing);

	/*
	 * If we are not connected to the Internet, apparently, make sure to
	 * connect to at most one host, to avoid using all our hostcache.
	 * Also, we don't connect each time we are called.
	 */

	if (!GNET_PROPERTY(is_inet_connected)) {
		static time_t last_try;

		if (last_try && delta_time(tm_time(), last_try) < 20)
			return;
		last_try = tm_time();

		if (GNET_PROPERTY(host_debug))
			g_debug("host_timer - not connected, trying to connect");
	}

	/*
	 * Allow more outgoing connections than the maximum amount of
	 * established Gnet connection we can maintain, but not more
	 * than quick_connect_pool_size   This is the "greedy mode".
	 */

	if (count >= GNET_PROPERTY(quick_connect_pool_size)) {
		if (GNET_PROPERTY(host_debug) > 1)
			g_debug("host_timer - count %u >= pool size %u",
				count, GNET_PROPERTY(quick_connect_pool_size));
		return;
	}

	if (count < max_nodes)
		missing -= whitelist_connect();

	/*
	 * If we are under the number of connections wanted, we add hosts
	 * to the connection list
	 */

	htype = HOST_ULTRA;

	if (
        settings_is_ultra() &&
        GNET_PROPERTY(node_normal_count) < GNET_PROPERTY(normal_connections) &&
        GNET_PROPERTY(node_ultra_count) >=
			(GNET_PROPERTY(up_connections) - GNET_PROPERTY(normal_connections))
	) {
		htype = HOST_ANY;
    }

	if (hcache_size(htype) == 0)
		htype = HOST_ANY;

	if (hcache_size(htype) == 0)
		empty_cache = TRUE;

	if (GNET_PROPERTY(host_debug) && missing > 0)
		g_debug("host_timer - missing %d host%s%s",
			missing, missing == 1 ? "" : "s",
			empty_cache ? " [empty caches]" : "");

    if (!GNET_PROPERTY(stop_host_get)) {
        if (missing > 0) {
			static time_t last_try;
            unsigned fan, max_pool, to_add;

            max_pool = MAX(GNET_PROPERTY(quick_connect_pool_size), max_nodes);
            fan = (missing * GNET_PROPERTY(quick_connect_pool_size))/ max_pool;
			fan = MAX(1, fan);
            to_add = GNET_PROPERTY(is_inet_connected) ? fan : (guint) missing;

			/*
			 * Every so many calls, attempt to ping all our neighbours to
			 * get fresh pongs, in case our host cache is not containing
			 * sufficiently fresh hosts and we keep getting connection failures.
			 */

			if (
				0 == last_try ||
				delta_time(tm_time(), last_try) >= HOST_PINGING_PERIOD
			) {
				ping_all_neighbours();
				last_try = tm_time();
			}

            /*
             * Make sure that we never use more connections then the
             * quick pool or the maximum number of hosts allow.
             */
            if (to_add + count > max_pool)
                to_add = max_pool - count;

            if (GNET_PROPERTY(host_debug) > 2) {
                g_debug("host_timer - connecting - "
					"add: %d fan:%d miss:%d max_hosts:%d count:%d extra:%d",
					 to_add, fan, missing, max_nodes, count,
					 GNET_PROPERTY(quick_connect_pool_size));
            }

            missing = to_add;

			if (missing > 0 && (0 == connected_nodes() || host_low_on_pongs)) {
				gnet_host_t host[HOST_DHT_MAX];
				int hcount;
				int i;

				hcount = dht_fill_random(host,
					MIN(UNSIGNED(missing), G_N_ELEMENTS(host)));

				missing -= hcount;

				for (i = 0; i < hcount; i++) {
					addr = gnet_host_get_addr(&host[i]);
					port = gnet_host_get_port(&host[i]);
					if (!hcache_node_is_bad(addr)) {
						if (GNET_PROPERTY(host_debug) > 3) {
							g_debug("host_timer - UHC pinging and connecting "
								"to DHT node at %s",
								host_addr_port_to_string(addr, port));
						}
						/* Try to use the host as an UHC before connecting */
						udp_send_ping(NULL, addr, port, TRUE);
						if (!host_gnutella_connect(addr, port)) {
							missing++;	/* Did not use entry */
						}
					} else {
						missing++;	/* Did not use entry */
					}
				}
			}

			while (hcache_size(htype) && missing-- > 0) {
				if (hcache_get_caught(htype, &addr, &port)) {
					if (!(hostiles_check(addr) || hcache_node_is_bad(addr))) {
						if (!host_gnutella_connect(addr, port)) {
							missing++;	/* Did not use entry */
						}
					} else {
						missing++;	/* Did not use entry */
					}
				}
			}

			if (missing > 0 && (empty_cache || host_cache_allow_bypass())) {
				if (!uhc_is_waiting()) {
					if (GNET_PROPERTY(host_debug))
						g_debug("host_timer - querying UDP host cache");
					uhc_get_hosts();	/* Get new hosts from UHCs */
				}
			}
		}

	} else if (GNET_PROPERTY(use_netmasks)) {
		/* Try to find better hosts */
		if (hcache_find_nearby(htype, &addr, &port)) {
			if (node_remove_worst(TRUE))
				node_add(addr, port, 0);
			else
				hcache_add_caught(htype, addr, port, "nearby host");
		}
	}
}
Exemple #7
0
/**
 * Called from gwc_parse_dispatch_lines() for each complete line of output.
 *
 * @return FALSE to stop processing of any remaining data.
 */
static bool
gwc_host_line(struct gwc_parse_context *ctx, const char *buf, size_t len)
{
    int c;

    if (GNET_PROPERTY(bootstrap_debug) > 3)
        g_message("BOOT GWC host line (%lu bytes): %s", (ulong) len, buf);

    if (is_strprefix(buf, "ERROR")) {
        g_warning("GWC cache \"%s\" returned %s",
                  http_async_url(ctx->handle), buf);
        http_async_cancel(ctx->handle);
        return FALSE;
    }

    if (len <= 2)
        return TRUE;		/* Skip this line silently */

    /*
     * A line starting with "H|" is a host, with "U|" a GWC URL.
     * Letters are case-insensitive.
     */

    if (buf[1] != '|')
        goto malformed;

    c = ascii_toupper(buf[0]);

    if ('H' == c) {
        host_addr_t addr;
        uint16 port;

        if (string_to_host_addr_port(&buf[2], NULL, &addr, &port)) {
            ctx->processed++;
            hcache_add_caught(HOST_G2HUB, addr, port, "GWC");
            if (GNET_PROPERTY(bootstrap_debug) > 1) {
                g_message("BOOT (G2) collected %s from GWC %s",
                          host_addr_port_to_string(addr, port),
                          http_async_url(ctx->handle));
            }
        }
        return TRUE;
    } else if ('U' == c) {
        char *end = strchr(&buf[2], '|');
        char *url;

        if (NULL == end)
            goto malformed;

        ctx->processed++;
        url = h_strndup(&buf[2], ptr_diff(end, &buf[2]));
        gwc_add(url);
        hfree(url);
        return TRUE;
    } else if ('I' == c) {
        return TRUE;		/* Ignore information line */
    }

    /*
     * If we come here, we did not recognize the line properly.
     */

    if (GNET_PROPERTY(bootstrap_debug) > 2) {
        g_warning("GWC ignoring unknown line \"%s\" from %s",
                  buf, http_async_url(ctx->handle));
    }

    return TRUE;

malformed:
    if (GNET_PROPERTY(bootstrap_debug)) {
        g_warning("GWC ignoring malformed line \"%s\" from %s",
                  buf, http_async_url(ctx->handle));
    }

    return TRUE;
}