/** * Pick host at random among the host array. * * @return TRUE if OK. */ static bool uhc_pick(void) { bool success = FALSE; char *uhc; uhc = uhc_get_next(); if (NULL == uhc) { if (GNET_PROPERTY(bootstrap_debug)) g_warning("BOOT ran out of UHCs, switching to GHCs"); ghc_get_hosts(); goto finish; } if (!uhc_get_host_port(uhc, &uhc_ctx.host, &uhc_ctx.port)) { g_warning("cannot parse UDP host cache \"%s\"", uhc); goto finish; } /* * Give GUI feedback. */ { char msg[256]; str_bprintf(msg, sizeof msg, _("Looking for UDP host cache %s"), uhc); gcu_statusbar_message(msg); } success = TRUE; finish: HFREE_NULL(uhc); return success; }
/** * Called from parse_dispatch_lines() on EOF. */ static void ghc_host_eof(struct parse_context *ctx) { char msg[256]; if (GNET_PROPERTY(bootstrap_debug) > 2) g_debug("BOOT GHC all done (%u/%u lines processed)", ctx->processed, ctx->lines); /* * Provide GUI feedback. */ str_bprintf(ARYLEN(msg), NG_("Got %d host from %s", "Got %d hosts from %s", ctx->processed), ctx->processed, http_async_url(ghc_ctx.ha)); gcu_statusbar_message(msg); if (GNET_PROPERTY(bootstrap_debug)) g_debug("BOOT GHC got %d host%s from %s", ctx->processed, plural(ctx->processed), http_async_url(ghc_ctx.ha)); ghc_ctx.ha = NULL; ghc_connecting = FALSE; }
/** * Called from gwc_parse_dispatch_lines() on EOF. */ static void gwc_host_eof(struct gwc_parse_context *ctx) { const char *msg; if (GNET_PROPERTY(bootstrap_debug) > 2) g_message("GWC host all done (%d/%d lines processed)", ctx->processed, ctx->lines); /* * Provide GUI feedback. */ msg = str_smsg( NG_("Got %d host from %s", "Got %d hosts from %s", ctx->processed), ctx->processed, gwc_current_url); gcu_statusbar_message(msg); if (GNET_PROPERTY(bootstrap_debug)) g_message("BOOT got %d host%s from GWC %s", ctx->processed, plural(ctx->processed), gwc_current_url); /* * If we did not get enough addresses, try to feed the cache with ours. */ if (ctx->processed < MIN_IP_LINES) { gwc_clear_current_url(FALSE); /* Move to another cache */ } gwc_get_running = FALSE; }
/** * 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); }
/** * Pick a random cache URL among the list we have. * * @return TRUE if OK. */ static bool ghc_pick(void) { bool success = FALSE; char *url; url = ghc_get_next(); if (NULL == url) { if (GNET_PROPERTY(bootstrap_debug)) g_warning("BOOT ran out of GHCs"); goto finish; } g_assert(NULL == ghc_ctx.ha); /* * Give GUI feedback. */ { char msg[256]; str_bprintf(ARYLEN(msg), _("Bootstrapping from %s"), url); gcu_statusbar_message(msg); } ghc_ctx.ha = http_async_get(url, NULL, ghc_data_ind, ghc_error_ind); if (!ghc_ctx.ha) { if (GNET_PROPERTY(bootstrap_debug)) g_warning("BOOT cannot launch a \"GET %s\" HTTP request: %s", url, http_async_strerror(http_async_errno)); goto finish; } parse_context_set(ghc_ctx.ha, GHC_MAX_HOSTS); success = TRUE; finish: HFREE_NULL(url); return success; }
/** * 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); } }
/** * Watcher callback, invoked when the file from which we read the * geographic IP mappings changed. */ static void gip_changed(const char *filename, void *idx_ptr) { FILE *f; char buf[80]; uint count; unsigned idx = pointer_to_uint(idx_ptr); f = file_fopen(filename, "r"); if (f == NULL) return; count = gip_load(f, idx); fclose(f); str_bprintf(buf, sizeof buf, "Reloaded %u geographic IPv%c ranges.", count, GIP_IPV4 == idx ? '4' : '6'); gcu_statusbar_message(buf); }
/** * Send an UDP ping to the host cache. */ static void uhc_send_ping(void) { g_assert(uhc_connecting); guid_random_muid(&uhc_ctx.muid); if (udp_send_ping(&uhc_ctx.muid, uhc_ctx.addr, uhc_ctx.port, TRUE)) { if (GNET_PROPERTY(bootstrap_debug) || GNET_PROPERTY(log_uhc_pings_tx)) { g_debug("BOOT sent UDP SCP ping #%s to %s:%u", guid_hex_str(&uhc_ctx.muid), uhc_ctx.host, uhc_ctx.port); } /* * Give GUI feedback. */ { char msg[256]; str_bprintf(msg, sizeof msg, _("Sent ping to UDP host cache %s:%u"), uhc_ctx.host, uhc_ctx.port); gcu_statusbar_message(msg); } /* * Arm a timer to see whether we should not try to ping another * host cache if we don't get a timely reply. */ g_assert(uhc_ctx.timeout_ev == NULL); uhc_ctx.timeout_ev = cq_main_insert(UHC_TIMEOUT, uhc_ping_timeout, NULL); } else { g_warning("BOOT failed to send UDP SCP to %s", host_addr_port_to_string(uhc_ctx.addr, uhc_ctx.port)); uhc_try_next(); } }
/** * 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(); } }
/** * Retrieve more hosts from web cache, asynchronously. */ void gwc_get_hosts(void) { void *handle; char *url; const char *msg; static time_t last_called = 0; time_t now = tm_time(); /* * Make sure we don't probe more than one webcache at a time. * Ancient versions should rely on their hostcache to be connected. */ if (gwc_get_running || GNET_PROPERTY(ancient_version)) return; /* * This routine is called each time we run out of hosts to try in our * cache, so we have absolutely no guarantee about the frequency at which * it will be called. * * Force picking up a new cache (well, randomly) if we were called less * than an hour ago. Note that we don't remember whether it was THIS * particular current cache that was accessed last time we were called. * We only care about the calling frequency, and bet on the high number * of available web caches and the random selection process to behave. * properly. * --RAM, 24/11/2003 */ if (delta_time(now, last_called) < REUSE_PERIOD) gwc_clear_current_url(FALSE); last_called = now; if (!gwc_check_current_url()) return; /* * Give some GUI feedback. */ msg = str_smsg(_("Connecting to web cache %s"), gwc_current_url); gcu_statusbar_message(msg); if (GNET_PROPERTY(bootstrap_debug)) g_message("BOOT connecting to web cache %s", gwc_current_url); /* * Launch the asynchronous request and attach parsing information. */ msg = str_smsg("%s?get=1&net=gnutella2&%s", gwc_current_url, CLIENT_INFO); url = h_strdup(msg); if (GNET_PROPERTY(bootstrap_debug) > 2) g_message("GWC host request: %s", url); handle = http_async_get(url, NULL, gwc_host_data_ind, gwc_host_error_ind); if (NULL == handle) { g_warning("could not launch a \"GET %s\" request: %s", url, http_async_strerror(http_async_errno)); gwc_clear_current_url(TRUE); } else { http_async_set_op_gotreply(handle, gwc_got_reply); gwc_parse_context_set(handle, MAX_IP_LINES); gwc_get_running = TRUE; } hfree(url); }