Merge remote-tracking branch 'asn/bug3589'

This commit is contained in:
Nick Mathewson 2012-07-17 12:05:08 -04:00
commit ec8bdc5da8
7 changed files with 360 additions and 298 deletions

3
changes/bug3589 Normal file
View File

@ -0,0 +1,3 @@
o Major features:
- Bridges now report the pluggable transports they support to the
bridge authority. Implements ticket 3589.

View File

@ -4970,199 +4970,6 @@ bridge_free(bridge_info_t *bridge)
tor_free(bridge);
}
/** A list of pluggable transports found in torrc. */
static smartlist_t *transport_list = NULL;
/** Mark every entry of the transport list to be removed on our next call to
* sweep_transport_list unless it has first been un-marked. */
void
mark_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH(transport_list, transport_t *, t,
t->marked_for_removal = 1);
}
/** Remove every entry of the transport list that was marked with
* mark_transport_list if it has not subsequently been un-marked. */
void
sweep_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
if (t->marked_for_removal) {
SMARTLIST_DEL_CURRENT(transport_list, t);
transport_free(t);
}
} SMARTLIST_FOREACH_END(t);
}
/** Initialize the pluggable transports list to empty, creating it if
* needed. */
void
clear_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
smartlist_clear(transport_list);
}
/** Free the pluggable transport struct <b>transport</b>. */
void
transport_free(transport_t *transport)
{
if (!transport)
return;
tor_free(transport->name);
tor_free(transport);
}
/** Returns the transport in our transport list that has the name <b>name</b>.
* Else returns NULL. */
transport_t *
transport_get_by_name(const char *name)
{
tor_assert(name);
if (!transport_list)
return NULL;
SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
if (!strcmp(transport->name, name))
return transport;
} SMARTLIST_FOREACH_END(transport);
return NULL;
}
/** Returns a transport_t struct for a transport proxy supporting the
protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
SOCKS version <b>socks_ver</b>. */
transport_t *
transport_new(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver)
{
transport_t *t = tor_malloc_zero(sizeof(transport_t));
tor_addr_copy(&t->addr, addr);
t->port = port;
t->name = tor_strdup(name);
t->socks_version = socks_ver;
return t;
}
/** Resolve any conflicts that the insertion of transport <b>t</b>
* might cause.
* Return 0 if <b>t</b> is OK and should be registered, 1 if there is
* a transport identical to <b>t</b> already registered and -1 if
* <b>t</b> cannot be added due to conflicts. */
static int
transport_resolve_conflicts(transport_t *t)
{
/* This is how we resolve transport conflicts:
If there is already a transport with the same name and addrport,
we either have duplicate torrc lines OR we are here post-HUP and
this transport was here pre-HUP as well. In any case, mark the
old transport so that it doesn't get removed and ignore the new
one. Our caller has to free the new transport so we return '1' to
signify this.
If there is already a transport with the same name but different
addrport:
* if it's marked for removal, it means that it either has a lower
priority than 't' in torrc (otherwise the mark would have been
cleared by the paragraph above), or it doesn't exist at all in
the post-HUP torrc. We destroy the old transport and register 't'.
* if it's *not* marked for removal, it means that it was newly
added in the post-HUP torrc or that it's of higher priority, in
this case we ignore 't'. */
transport_t *t_tmp = transport_get_by_name(t->name);
if (t_tmp) { /* same name */
if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
/* same name *and* addrport */
t_tmp->marked_for_removal = 0;
return 1;
} else { /* same name but different addrport */
if (t_tmp->marked_for_removal) { /* marked for removal */
log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
"but there was already a transport marked for deletion at "
"'%s:%u'. We deleted the old transport and registered the "
"new one.", t->name, fmt_addr(&t->addr), t->port,
fmt_addr(&t_tmp->addr), t_tmp->port);
smartlist_remove(transport_list, t_tmp);
transport_free(t_tmp);
} else { /* *not* marked for removal */
log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
"but the same transport already exists at '%s:%u'. "
"Skipping.", t->name, fmt_addr(&t->addr), t->port,
fmt_addr(&t_tmp->addr), t_tmp->port);
return -1;
}
}
}
return 0;
}
/** Add transport <b>t</b> to the internal list of pluggable
* transports.
* Returns 0 if the transport was added correctly, 1 if the same
* transport was already registered (in this case the caller must
* free the transport) and -1 if there was an error. */
int
transport_add(transport_t *t)
{
int r;
tor_assert(t);
r = transport_resolve_conflicts(t);
switch (r) {
case 0: /* should register transport */
if (!transport_list)
transport_list = smartlist_new();
smartlist_add(transport_list, t);
return 0;
default: /* let our caller know the return code */
return r;
}
}
/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
* <b>name</b> is set to the name of the protocol this proxy uses.
* <b>socks_ver</b> is set to the SOCKS version of the proxy. */
int
transport_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver)
{
transport_t *t = transport_new(addr, port, name, socks_ver);
int r = transport_add(t);
switch (r) {
case -1:
default:
log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
t->name, fmt_addr(&t->addr), t->port);
transport_free(t);
return -1;
case 1:
log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
t->name, fmt_addr(&t->addr), t->port);
transport_free(t); /* falling */
return 0;
case 0:
log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
t->name, fmt_addr(&t->addr), t->port);
return 0;
}
}
/** Return a bridge pointer if <b>ri</b> is one of our known bridges
* (either by comparing keys if possible, else by comparing addr/port).
@ -5800,10 +5607,7 @@ entry_guards_free_all(void)
entry_guards = NULL;
}
clear_bridge_list();
clear_transport_list();
smartlist_free(bridge_list);
smartlist_free(transport_list);
bridge_list = NULL;
transport_list = NULL;
}

View File

@ -12,21 +12,6 @@
#ifndef _TOR_CIRCUITBUILD_H
#define _TOR_CIRCUITBUILD_H
/** Represents a pluggable transport proxy used by a bridge. */
typedef struct {
/** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
int socks_version;
/** Name of pluggable transport protocol */
char *name;
/** Address of proxy */
tor_addr_t addr;
/** Port of proxy */
uint16_t port;
/** Boolean: We are re-parsing our transport list, and we are going to remove
* this one if we don't find it in the list of configured transports. */
unsigned marked_for_removal : 1;
} transport_t;
char *circuit_list_path(origin_circuit_t *circ, int verbose);
char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain,
@ -82,8 +67,6 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void mark_bridge_list(void);
void sweep_bridge_list(void);
void mark_transport_list(void);
void sweep_transport_list(void);
int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
int node_is_a_configured_bridge(const node_t *node);
@ -151,21 +134,12 @@ void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
/* DOCDOC circuit_build_times_get_bw_scale */
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
void clear_transport_list(void);
int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver);
int transport_add(transport_t *t);
void transport_free(transport_t *transport);
transport_t *transport_new(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver);
/* DOCDOC find_transport_name_by_bridge_addrport */
const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
uint16_t port);
typedef struct transport_t transport_t;
int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
const transport_t **transport);
transport_t *transport_get_by_name(const char *name);
#endif

View File

@ -34,6 +34,7 @@
#include "rendcommon.h"
#include "rephist.h"
#include "router.h"
#include "transports.h"
#include "routerparse.h"
#ifdef USE_BUFFEREVENTS

View File

@ -27,6 +27,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
#include "transports.h"
/**
* \file router.c
@ -2344,6 +2345,13 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
}
}
/* Add information about the pluggable transports we support. */
if (options->ServerTransportPlugin) {
char *pluggable_transports = pt_get_extra_info_descriptor_string();
if (pluggable_transports)
smartlist_add(chunks, pluggable_transports);
}
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
if (bridge_stats) {

View File

@ -39,13 +39,17 @@
* transport_t structs.
*
* When the managed proxy stops spitting METHOD lines (signified by a
* '{S,C}METHODS DONE' message) we register all the transports
* collected to the circuitbuild.c subsystem. At this point, the
* pointers to transport_t can be transformed into dangling pointers
* at any point by the circuitbuild.c subsystem, and so we replace all
* transport_t pointers with strings describing the transport names.
* We can still go from a transport name to a transport_t using the
* fact that each transport name uniquely identifies a transport_t.
* '{S,C}METHODS DONE' message) we pass copies of its transports to
* the bridge subsystem. We keep copies of the 'transport_t's on the
* managed proxy to be able to associate the proxy with its
* transports, and we pass copies to the bridge subsystem so that
* transports can be associated with bridges.
* [ XXX We should try see whether the two copies are really needed
* and maybe cut it into a single copy of the 'transport_t' shared
* between the managed proxy and the bridge subsystem. Preliminary
* analysis shows that both copies are needed with the current code
* logic, because of race conditions that can cause dangling
* pointers. ]
*
* <b>In even more detail, this is what happens when a SIGHUP
* occurs:</b>
@ -127,6 +131,219 @@ static INLINE void free_execve_args(char **arg);
protocol version. */
#define PROTO_VERSION_ONE 1
/** A list of pluggable transports found in torrc. */
static smartlist_t *transport_list = NULL;
/** Returns a transport_t struct for a transport proxy supporting the
protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
SOCKS version <b>socks_ver</b>. */
static transport_t *
transport_new(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver)
{
transport_t *t = tor_malloc_zero(sizeof(transport_t));
tor_addr_copy(&t->addr, addr);
t->port = port;
t->name = tor_strdup(name);
t->socks_version = socks_ver;
return t;
}
/** Free the pluggable transport struct <b>transport</b>. */
void
transport_free(transport_t *transport)
{
if (!transport)
return;
tor_free(transport->name);
tor_free(transport);
}
/** Mark every entry of the transport list to be removed on our next call to
* sweep_transport_list unless it has first been un-marked. */
void
mark_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH(transport_list, transport_t *, t,
t->marked_for_removal = 1);
}
/** Remove every entry of the transport list that was marked with
* mark_transport_list if it has not subsequently been un-marked. */
void
sweep_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
if (t->marked_for_removal) {
SMARTLIST_DEL_CURRENT(transport_list, t);
transport_free(t);
}
} SMARTLIST_FOREACH_END(t);
}
/** Initialize the pluggable transports list to empty, creating it if
* needed. */
static void
clear_transport_list(void)
{
if (!transport_list)
transport_list = smartlist_new();
SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
smartlist_clear(transport_list);
}
/** Return a deep copy of <b>transport</b>. */
static transport_t *
transport_copy(const transport_t *transport)
{
transport_t *new_transport = NULL;
tor_assert(transport);
new_transport = tor_malloc_zero(sizeof(transport_t));
new_transport->socks_version = transport->socks_version;
new_transport->name = tor_strdup(transport->name);
tor_addr_copy(&new_transport->addr, &transport->addr);
new_transport->port = transport->port;
new_transport->marked_for_removal = transport->marked_for_removal;
return new_transport;
}
/** Returns the transport in our transport list that has the name <b>name</b>.
* Else returns NULL. */
transport_t *
transport_get_by_name(const char *name)
{
tor_assert(name);
if (!transport_list)
return NULL;
SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
if (!strcmp(transport->name, name))
return transport;
} SMARTLIST_FOREACH_END(transport);
return NULL;
}
/** Resolve any conflicts that the insertion of transport <b>t</b>
* might cause.
* Return 0 if <b>t</b> is OK and should be registered, 1 if there is
* a transport identical to <b>t</b> already registered and -1 if
* <b>t</b> cannot be added due to conflicts. */
static int
transport_resolve_conflicts(const transport_t *t)
{
/* This is how we resolve transport conflicts:
If there is already a transport with the same name and addrport,
we either have duplicate torrc lines OR we are here post-HUP and
this transport was here pre-HUP as well. In any case, mark the
old transport so that it doesn't get removed and ignore the new
one. Our caller has to free the new transport so we return '1' to
signify this.
If there is already a transport with the same name but different
addrport:
* if it's marked for removal, it means that it either has a lower
priority than 't' in torrc (otherwise the mark would have been
cleared by the paragraph above), or it doesn't exist at all in
the post-HUP torrc. We destroy the old transport and register 't'.
* if it's *not* marked for removal, it means that it was newly
added in the post-HUP torrc or that it's of higher priority, in
this case we ignore 't'. */
transport_t *t_tmp = transport_get_by_name(t->name);
if (t_tmp) { /* same name */
if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
/* same name *and* addrport */
t_tmp->marked_for_removal = 0;
return 1;
} else { /* same name but different addrport */
if (t_tmp->marked_for_removal) { /* marked for removal */
log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
"but there was already a transport marked for deletion at "
"'%s:%u'. We deleted the old transport and registered the "
"new one.", t->name, fmt_addr(&t->addr), t->port,
fmt_addr(&t_tmp->addr), t_tmp->port);
smartlist_remove(transport_list, t_tmp);
transport_free(t_tmp);
} else { /* *not* marked for removal */
log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
"but the same transport already exists at '%s:%u'. "
"Skipping.", t->name, fmt_addr(&t->addr), t->port,
fmt_addr(&t_tmp->addr), t_tmp->port);
return -1;
}
}
}
return 0;
}
/** Add transport <b>t</b> to the internal list of pluggable
* transports.
* Returns 0 if the transport was added correctly, 1 if the same
* transport was already registered (in this case the caller must
* free the transport) and -1 if there was an error. */
static int
transport_add(transport_t *t)
{
int r;
tor_assert(t);
r = transport_resolve_conflicts(t);
switch (r) {
case 0: /* should register transport */
if (!transport_list)
transport_list = smartlist_new();
smartlist_add(transport_list, t);
return 0;
default: /* let our caller know the return code */
return r;
}
}
/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
* <b>name</b> is set to the name of the protocol this proxy uses.
* <b>socks_ver</b> is set to the SOCKS version of the proxy. */
int
transport_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver)
{
transport_t *t = transport_new(addr, port, name, socks_ver);
int r = transport_add(t);
switch (r) {
case -1:
default:
log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
t->name, fmt_addr(&t->addr), t->port);
transport_free(t);
return -1;
case 1:
log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
t->name, fmt_addr(&t->addr), t->port);
transport_free(t); /* falling */
return 0;
case 0:
log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
t->name, fmt_addr(&t->addr), t->port);
return 0;
}
}
/** List of unconfigured managed proxies. */
static smartlist_t *managed_proxy_list = NULL;
/** Number of still unconfigured proxies. */
@ -217,11 +434,11 @@ proxy_needs_restart(const managed_proxy_t *mp)
{
/* mp->transport_to_launch is populated with the names of the
transports that must be launched *after* the SIGHUP.
mp->transports is populated with the names of the transports that
were launched *before* the SIGHUP.
mp->transports is populated with the transports that were
launched *before* the SIGHUP.
If the two lists contain the same strings, we don't need to
restart the proxy, since it already does what we want. */
Check if all the transports that need to be launched are already
launched: */
tor_assert(smartlist_len(mp->transports_to_launch) > 0);
tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
@ -229,11 +446,11 @@ proxy_needs_restart(const managed_proxy_t *mp)
if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
goto needs_restart;
SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
if (!smartlist_string_isin(mp->transports, t_t_l))
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
if (!smartlist_string_isin(mp->transports_to_launch, t->name))
goto needs_restart;
} SMARTLIST_FOREACH_END(t_t_l);
} SMARTLIST_FOREACH_END(t);
return 0;
@ -245,6 +462,7 @@ proxy_needs_restart(const managed_proxy_t *mp)
* preparations and then flag its state so that it will be relaunched
* in the next tick. */
static void
proxy_prepare_for_restart(managed_proxy_t *mp)
{
transport_t *t_tmp = NULL;
@ -255,16 +473,17 @@ proxy_prepare_for_restart(managed_proxy_t *mp)
tor_process_handle_destroy(mp->process_handle, 1);
mp->process_handle = NULL;
/* destroy all its old transports. we no longer use them. */
SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
t_tmp = transport_get_by_name(t_name);
/* destroy all its registered transports, since we will no longer
use them. */
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
t_tmp = transport_get_by_name(t->name);
if (t_tmp)
t_tmp->marked_for_removal = 1;
} SMARTLIST_FOREACH_END(t_name);
} SMARTLIST_FOREACH_END(t);
sweep_transport_list();
/* free the transport names in mp->transports */
SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
/* free the transport in mp->transports */
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
smartlist_clear(mp->transports);
/* flag it as an infant proxy so that it gets launched on next tick */
@ -315,6 +534,7 @@ launch_managed_proxy(managed_proxy_t *mp)
void
pt_configure_remaining_proxies(void)
{
int at_least_a_proxy_config_finished = 0;
smartlist_t *tmp = smartlist_new();
log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
@ -352,11 +572,17 @@ pt_configure_remaining_proxies(void)
if (!proxy_configuration_finished(mp))
configure_proxy(mp);
if (proxy_configuration_finished(mp))
at_least_a_proxy_config_finished = 1;
} SMARTLIST_FOREACH_END(mp);
smartlist_free(tmp);
check_if_restarts_needed = 0;
assert_unconfigured_count_ok();
if (at_least_a_proxy_config_finished)
mark_my_descriptor_dirty("configured managed proxies");
}
#ifdef _WIN32
@ -468,68 +694,48 @@ configure_proxy(managed_proxy_t *mp)
/** Register server managed proxy <b>mp</b> transports to state */
static void
register_server_proxy(managed_proxy_t *mp)
register_server_proxy(const managed_proxy_t *mp)
{
/* After we register this proxy's transports, we switch its
mp->transports to a list containing strings of its transport
names. (See transports.h) */
smartlist_t *sm_tmp = smartlist_new();
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
save_transport_to_state(t->name, &t->addr, t->port);
log_notice(LD_GENERAL, "Registered server transport '%s' at '%s:%d'",
t->name, fmt_addr(&t->addr), (int)t->port);
smartlist_add(sm_tmp, tor_strdup(t->name));
} SMARTLIST_FOREACH_END(t);
/* Since server proxies don't register their transports in the
circuitbuild.c subsystem, it's our duty to free them when we
switch mp->transports to strings. */
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
smartlist_free(mp->transports);
mp->transports = sm_tmp;
}
/** Register all the transports supported by client managed proxy
* <b>mp</b> to the bridge subsystem. */
static void
register_client_proxy(managed_proxy_t *mp)
register_client_proxy(const managed_proxy_t *mp)
{
int r;
/* After we register this proxy's transports, we switch its
mp->transports to a list containing strings of its transport
names. (See transports.h) */
smartlist_t *sm_tmp = smartlist_new();
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
r = transport_add(t);
transport_t *transport_tmp = transport_copy(t);
r = transport_add(transport_tmp);
switch (r) {
case -1:
log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
transport_free(t);
transport_free(transport_tmp);
break;
case 0:
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
smartlist_add(sm_tmp, tor_strdup(t->name));
break;
case 1:
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
smartlist_add(sm_tmp, tor_strdup(t->name));
transport_free(t);
transport_free(transport_tmp);
break;
}
} SMARTLIST_FOREACH_END(t);
smartlist_free(mp->transports);
mp->transports = sm_tmp;
}
/** Register the transports of managed proxy <b>mp</b>. */
static INLINE void
register_proxy(managed_proxy_t *mp)
register_proxy(const managed_proxy_t *mp)
{
if (mp->is_server)
register_server_proxy(mp);
@ -542,10 +748,7 @@ static void
managed_proxy_destroy(managed_proxy_t *mp,
int also_terminate_process)
{
if (mp->conf_state != PT_PROTO_COMPLETED)
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
else
SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
/* free the transports smartlist */
smartlist_free(mp->transports);
@ -1181,6 +1384,64 @@ pt_prepare_proxy_list_for_config_read(void)
tor_assert(unconfigured_proxies_n == 0);
}
/** Return the pluggable transport string that we should display in
* our extra-info descriptor. If we shouldn't display such a string,
* or we have nothing to display, return NULL. The string is
* allocated on the heap and it's the responsibility of the caller to
* free it. */
char *
pt_get_extra_info_descriptor_string(void)
{
char *the_string = NULL;
smartlist_t *string_chunks = NULL;
if (!managed_proxy_list)
return NULL;
string_chunks = smartlist_new();
/* For each managed proxy, add its transports to the chunks list. */
SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
continue;
tor_assert(mp->transports);
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
/* If the transport proxy returned "0.0.0.0" as its address, and
* we know our external IP address, use it. Otherwise, use the
* returned address. */
const char *addr_str = fmt_addr(&t->addr);
uint32_t external_ip_address = 0;
if (tor_addr_is_null(&t->addr) &&
router_pick_published_address(get_options(),
&external_ip_address) >= 0) {
/* returned addr was 0.0.0.0 and we found our external IP
address: use it. */
addr_str = fmt_addr32(external_ip_address);
}
smartlist_add_asprintf(string_chunks,
"transport %s %s:%u",
t->name, addr_str, t->port);
} SMARTLIST_FOREACH_END(t);
} SMARTLIST_FOREACH_END(mp);
if (smartlist_len(string_chunks) == 0) {
smartlist_free(string_chunks);
return NULL;
}
/* Join all the chunks into the final string. */
the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
smartlist_free(string_chunks);
return the_string;
}
/** The tor config was read.
* Destroy all managed proxies that were marked by a previous call to
* prepare_proxy_list_for_config_read() and are not used by the new
@ -1204,6 +1465,12 @@ sweep_proxy_list(void)
void
pt_free_all(void)
{
if (transport_list) {
clear_transport_list();
smartlist_free(transport_list);
transport_list = NULL;
}
if (managed_proxy_list) {
/* If the proxy is in PT_PROTO_COMPLETED, it has registered its
transports and it's the duty of the circuitbuild.c subsystem to

View File

@ -11,6 +11,30 @@
#ifndef TOR_TRANSPORTS_H
#define TOR_TRANSPORTS_H
/** Represents a pluggable transport used by a bridge. */
typedef struct transport_t {
/** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
int socks_version;
/** Name of pluggable transport protocol */
char *name;
/** The IP address where the transport bound and is waiting for
* connections. */
tor_addr_t addr;
/** Port of proxy */
uint16_t port;
/** Boolean: We are re-parsing our transport list, and we are going to remove
* this one if we don't find it in the list of configured transports. */
unsigned marked_for_removal : 1;
} transport_t;
void mark_transport_list(void);
void sweep_transport_list(void);
int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver);
void transport_free(transport_t *transport);
transport_t *transport_get_by_name(const char *name);
void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv,
int is_server);
@ -23,6 +47,8 @@ void pt_configure_remaining_proxies(void);
int pt_proxies_configuration_pending(void);
char *pt_get_extra_info_descriptor_string(void);
void pt_free_all(void);
void pt_prepare_proxy_list_for_config_read(void);
@ -68,28 +94,7 @@ typedef struct {
smartlist_t *transports_to_launch;
/* The 'transports' list contains all the transports this proxy has
launched.
Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase,
this smartlist contains a 'transport_t' for every transport it
has launched.
When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it
registers all its transports to the circuitbuild.c subsystem. At
that point the 'transport_t's are owned by the circuitbuild.c
subsystem.
To avoid carrying dangling 'transport_t's in this smartlist,
right before the managed_proxy_t reaches the PT_PROTO_COMPLETED
phase we replace all 'transport_t's with strings of their
transport names.
So, tl;dr:
When (conf_state != PT_PROTO_COMPLETED) this list carries
(transport_t *).
When (conf_state == PT_PROTO_COMPLETED) this list carries
(char *).
*/
launched. */
smartlist_t *transports;
} managed_proxy_t;