/** * 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; }
/** * Add a port forwarding (*:ext_port -> addr:port) [IP or PPP connection]. * * @param usd the UPnP service to contact * @param proto mapping protocol * @param ext_port the mapped external port for which we want the mapping * @param int_addr the internal client address * @param int_port the internal port for which we want the mapping * @param desc comment description * @param lease lease duration (0 = permanent) * @param cb callback to invoke when reply is available * @param arg additional callback argument * * @return UPnP request handle if the SOAP RPC was initiated, NULL otherwise * (in which case callbacks will never be called). */ upnp_ctrl_t * upnp_ctrl_AddPortMapping(const upnp_service_t *usd, enum upnp_map_proto proto, guint16 ext_port, host_addr_t int_addr, guint16 int_port, const char *desc, time_delta_t lease, upnp_ctrl_cb_t cb, void *arg) { nv_pair_t *argv[8]; char ext_port_buf[UINT16_DEC_BUFLEN]; char int_port_buf[UINT16_DEC_BUFLEN]; char int_addr_buf[HOST_ADDR_BUFLEN]; char lease_buf[UINT32_DEC_BUFLEN]; const char *protocol; const char *description; g_assert(lease >= 0); g_assert(lease <= MAX_INT_VAL(gint32)); g_assert(ext_port != 0); g_assert(int_port != 0); int32_to_string_buf(ext_port, ext_port_buf, sizeof ext_port_buf); int32_to_string_buf(int_port, int_port_buf, sizeof int_port_buf); host_addr_to_string_buf(int_addr, int_addr_buf, sizeof int_addr_buf); protocol = upnp_map_proto_to_string(proto); int32_to_string_buf(lease, lease_buf, sizeof lease_buf); description = str_smsg("%s (%s)", desc, protocol); argv[0] = nv_pair_make_static_str(ARG_REMOTE_HOST, EMPTY); /* Wildcard */ argv[1] = nv_pair_make_static_str(ARG_EXTERNAL_PORT, ext_port_buf); argv[2] = nv_pair_make_static_str(ARG_PROTOCOL, protocol); argv[3] = nv_pair_make_static_str(ARG_INTERNAL_PORT, int_port_buf); argv[4] = nv_pair_make_static_str(ARG_INTERNAL_CLIENT, int_addr_buf); argv[5] = nv_pair_make_static_str(ARG_ENABLED, ONE); /* Enable! */ argv[6] = nv_pair_make_static_str(ARG_PORTMAP_DESC, description); argv[7] = nv_pair_make_static_str(ARG_LEASE_DURATION, lease_buf); /* * TODO: when talking to a v2 WANIPConnection service, we can use * the AddAnyPortMapping() call. This will require that GTKG maintains * knowledge about the remote port so that it can advertise that remote * port instead of the local listening port. * * Attempts must be made to get the same external port for both TCP and UDP, * or this will create problems to servents assuming that they will always * be identical (like GTKG does when it uses the TCP listening port of * a remote host to send a push-proxy request via UDP).. * --RAM, 2011-01-18 */ return upnp_ctrl_launch(usd, "AddPortMapping", argv, G_N_ELEMENTS(argv), cb, arg, NULL); }
/** * 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); }