mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge remote-tracking branch 'asn/bug3589'
This commit is contained in:
commit
ec8bdc5da8
3
changes/bug3589
Normal file
3
changes/bug3589
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
o Major features:
|
||||||
|
- Bridges now report the pluggable transports they support to the
|
||||||
|
bridge authority. Implements ticket 3589.
|
@ -4970,199 +4970,6 @@ bridge_free(bridge_info_t *bridge)
|
|||||||
tor_free(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
|
/** 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).
|
* (either by comparing keys if possible, else by comparing addr/port).
|
||||||
@ -5800,10 +5607,7 @@ entry_guards_free_all(void)
|
|||||||
entry_guards = NULL;
|
entry_guards = NULL;
|
||||||
}
|
}
|
||||||
clear_bridge_list();
|
clear_bridge_list();
|
||||||
clear_transport_list();
|
|
||||||
smartlist_free(bridge_list);
|
smartlist_free(bridge_list);
|
||||||
smartlist_free(transport_list);
|
|
||||||
bridge_list = NULL;
|
bridge_list = NULL;
|
||||||
transport_list = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,21 +12,6 @@
|
|||||||
#ifndef _TOR_CIRCUITBUILD_H
|
#ifndef _TOR_CIRCUITBUILD_H
|
||||||
#define _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(origin_circuit_t *circ, int verbose);
|
||||||
char *circuit_list_path_for_controller(origin_circuit_t *circ);
|
char *circuit_list_path_for_controller(origin_circuit_t *circ);
|
||||||
void circuit_log_path(int severity, unsigned int domain,
|
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 mark_bridge_list(void);
|
||||||
void sweep_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 routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
|
||||||
int node_is_a_configured_bridge(const node_t *node);
|
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 */
|
/* DOCDOC circuit_build_times_get_bw_scale */
|
||||||
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
|
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 */
|
/* DOCDOC find_transport_name_by_bridge_addrport */
|
||||||
const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
|
const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
|
||||||
uint16_t port);
|
uint16_t port);
|
||||||
|
typedef struct transport_t transport_t;
|
||||||
int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
|
int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
|
||||||
const transport_t **transport);
|
const transport_t **transport);
|
||||||
transport_t *transport_get_by_name(const char *name);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "rendcommon.h"
|
#include "rendcommon.h"
|
||||||
#include "rephist.h"
|
#include "rephist.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
|
#include "transports.h"
|
||||||
#include "routerparse.h"
|
#include "routerparse.h"
|
||||||
|
|
||||||
#ifdef USE_BUFFEREVENTS
|
#ifdef USE_BUFFEREVENTS
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include "routerlist.h"
|
#include "routerlist.h"
|
||||||
#include "routerparse.h"
|
#include "routerparse.h"
|
||||||
|
#include "transports.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file router.c
|
* \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) {
|
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
|
||||||
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
|
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
|
||||||
if (bridge_stats) {
|
if (bridge_stats) {
|
||||||
|
@ -39,13 +39,17 @@
|
|||||||
* transport_t structs.
|
* transport_t structs.
|
||||||
*
|
*
|
||||||
* When the managed proxy stops spitting METHOD lines (signified by a
|
* When the managed proxy stops spitting METHOD lines (signified by a
|
||||||
* '{S,C}METHODS DONE' message) we register all the transports
|
* '{S,C}METHODS DONE' message) we pass copies of its transports to
|
||||||
* collected to the circuitbuild.c subsystem. At this point, the
|
* the bridge subsystem. We keep copies of the 'transport_t's on the
|
||||||
* pointers to transport_t can be transformed into dangling pointers
|
* managed proxy to be able to associate the proxy with its
|
||||||
* at any point by the circuitbuild.c subsystem, and so we replace all
|
* transports, and we pass copies to the bridge subsystem so that
|
||||||
* transport_t pointers with strings describing the transport names.
|
* transports can be associated with bridges.
|
||||||
* We can still go from a transport name to a transport_t using the
|
* [ XXX We should try see whether the two copies are really needed
|
||||||
* fact that each transport name uniquely identifies a transport_t.
|
* 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
|
* <b>In even more detail, this is what happens when a SIGHUP
|
||||||
* occurs:</b>
|
* occurs:</b>
|
||||||
@ -127,6 +131,219 @@ static INLINE void free_execve_args(char **arg);
|
|||||||
protocol version. */
|
protocol version. */
|
||||||
#define PROTO_VERSION_ONE 1
|
#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. */
|
/** List of unconfigured managed proxies. */
|
||||||
static smartlist_t *managed_proxy_list = NULL;
|
static smartlist_t *managed_proxy_list = NULL;
|
||||||
/** Number of still unconfigured proxies. */
|
/** 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
|
/* mp->transport_to_launch is populated with the names of the
|
||||||
transports that must be launched *after* the SIGHUP.
|
transports that must be launched *after* the SIGHUP.
|
||||||
mp->transports is populated with the names of the transports that
|
mp->transports is populated with the transports that were
|
||||||
were launched *before* the SIGHUP.
|
launched *before* the SIGHUP.
|
||||||
|
|
||||||
If the two lists contain the same strings, we don't need to
|
Check if all the transports that need to be launched are already
|
||||||
restart the proxy, since it already does what we want. */
|
launched: */
|
||||||
|
|
||||||
tor_assert(smartlist_len(mp->transports_to_launch) > 0);
|
tor_assert(smartlist_len(mp->transports_to_launch) > 0);
|
||||||
tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
|
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))
|
if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
|
||||||
goto needs_restart;
|
goto needs_restart;
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
|
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
|
||||||
if (!smartlist_string_isin(mp->transports, t_t_l))
|
if (!smartlist_string_isin(mp->transports_to_launch, t->name))
|
||||||
goto needs_restart;
|
goto needs_restart;
|
||||||
|
|
||||||
} SMARTLIST_FOREACH_END(t_t_l);
|
} SMARTLIST_FOREACH_END(t);
|
||||||
|
|
||||||
return 0;
|
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
|
* preparations and then flag its state so that it will be relaunched
|
||||||
* in the next tick. */
|
* in the next tick. */
|
||||||
static void
|
static void
|
||||||
|
|
||||||
proxy_prepare_for_restart(managed_proxy_t *mp)
|
proxy_prepare_for_restart(managed_proxy_t *mp)
|
||||||
{
|
{
|
||||||
transport_t *t_tmp = NULL;
|
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);
|
tor_process_handle_destroy(mp->process_handle, 1);
|
||||||
mp->process_handle = NULL;
|
mp->process_handle = NULL;
|
||||||
|
|
||||||
/* destroy all its old transports. we no longer use them. */
|
/* destroy all its registered transports, since we will no longer
|
||||||
SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
|
use them. */
|
||||||
t_tmp = transport_get_by_name(t_name);
|
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
|
||||||
|
t_tmp = transport_get_by_name(t->name);
|
||||||
if (t_tmp)
|
if (t_tmp)
|
||||||
t_tmp->marked_for_removal = 1;
|
t_tmp->marked_for_removal = 1;
|
||||||
} SMARTLIST_FOREACH_END(t_name);
|
} SMARTLIST_FOREACH_END(t);
|
||||||
sweep_transport_list();
|
sweep_transport_list();
|
||||||
|
|
||||||
/* free the transport names in mp->transports */
|
/* free the transport in mp->transports */
|
||||||
SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
|
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
|
||||||
smartlist_clear(mp->transports);
|
smartlist_clear(mp->transports);
|
||||||
|
|
||||||
/* flag it as an infant proxy so that it gets launched on next tick */
|
/* 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
|
void
|
||||||
pt_configure_remaining_proxies(void)
|
pt_configure_remaining_proxies(void)
|
||||||
{
|
{
|
||||||
|
int at_least_a_proxy_config_finished = 0;
|
||||||
smartlist_t *tmp = smartlist_new();
|
smartlist_t *tmp = smartlist_new();
|
||||||
|
|
||||||
log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
|
log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
|
||||||
@ -352,11 +572,17 @@ pt_configure_remaining_proxies(void)
|
|||||||
if (!proxy_configuration_finished(mp))
|
if (!proxy_configuration_finished(mp))
|
||||||
configure_proxy(mp);
|
configure_proxy(mp);
|
||||||
|
|
||||||
|
if (proxy_configuration_finished(mp))
|
||||||
|
at_least_a_proxy_config_finished = 1;
|
||||||
|
|
||||||
} SMARTLIST_FOREACH_END(mp);
|
} SMARTLIST_FOREACH_END(mp);
|
||||||
|
|
||||||
smartlist_free(tmp);
|
smartlist_free(tmp);
|
||||||
check_if_restarts_needed = 0;
|
check_if_restarts_needed = 0;
|
||||||
assert_unconfigured_count_ok();
|
assert_unconfigured_count_ok();
|
||||||
|
|
||||||
|
if (at_least_a_proxy_config_finished)
|
||||||
|
mark_my_descriptor_dirty("configured managed proxies");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -468,68 +694,48 @@ configure_proxy(managed_proxy_t *mp)
|
|||||||
|
|
||||||
/** Register server managed proxy <b>mp</b> transports to state */
|
/** Register server managed proxy <b>mp</b> transports to state */
|
||||||
static void
|
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);
|
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
||||||
save_transport_to_state(t->name, &t->addr, t->port);
|
save_transport_to_state(t->name, &t->addr, t->port);
|
||||||
log_notice(LD_GENERAL, "Registered server transport '%s' at '%s:%d'",
|
log_notice(LD_GENERAL, "Registered server transport '%s' at '%s:%d'",
|
||||||
t->name, fmt_addr(&t->addr), (int)t->port);
|
t->name, fmt_addr(&t->addr), (int)t->port);
|
||||||
smartlist_add(sm_tmp, tor_strdup(t->name));
|
|
||||||
} SMARTLIST_FOREACH_END(t);
|
} 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
|
/** Register all the transports supported by client managed proxy
|
||||||
* <b>mp</b> to the bridge subsystem. */
|
* <b>mp</b> to the bridge subsystem. */
|
||||||
static void
|
static void
|
||||||
register_client_proxy(managed_proxy_t *mp)
|
register_client_proxy(const managed_proxy_t *mp)
|
||||||
{
|
{
|
||||||
int r;
|
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);
|
tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
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) {
|
switch (r) {
|
||||||
case -1:
|
case -1:
|
||||||
log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
|
log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
|
||||||
transport_free(t);
|
transport_free(transport_tmp);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
||||||
smartlist_add(sm_tmp, tor_strdup(t->name));
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
||||||
smartlist_add(sm_tmp, tor_strdup(t->name));
|
transport_free(transport_tmp);
|
||||||
transport_free(t);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} SMARTLIST_FOREACH_END(t);
|
} SMARTLIST_FOREACH_END(t);
|
||||||
|
|
||||||
smartlist_free(mp->transports);
|
|
||||||
mp->transports = sm_tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Register the transports of managed proxy <b>mp</b>. */
|
/** Register the transports of managed proxy <b>mp</b>. */
|
||||||
static INLINE void
|
static INLINE void
|
||||||
register_proxy(managed_proxy_t *mp)
|
register_proxy(const managed_proxy_t *mp)
|
||||||
{
|
{
|
||||||
if (mp->is_server)
|
if (mp->is_server)
|
||||||
register_server_proxy(mp);
|
register_server_proxy(mp);
|
||||||
@ -542,10 +748,7 @@ static void
|
|||||||
managed_proxy_destroy(managed_proxy_t *mp,
|
managed_proxy_destroy(managed_proxy_t *mp,
|
||||||
int also_terminate_process)
|
int also_terminate_process)
|
||||||
{
|
{
|
||||||
if (mp->conf_state != PT_PROTO_COMPLETED)
|
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
|
||||||
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
|
|
||||||
else
|
|
||||||
SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
|
|
||||||
|
|
||||||
/* free the transports smartlist */
|
/* free the transports smartlist */
|
||||||
smartlist_free(mp->transports);
|
smartlist_free(mp->transports);
|
||||||
@ -1181,6 +1384,64 @@ pt_prepare_proxy_list_for_config_read(void)
|
|||||||
tor_assert(unconfigured_proxies_n == 0);
|
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.
|
/** The tor config was read.
|
||||||
* Destroy all managed proxies that were marked by a previous call to
|
* 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
|
* prepare_proxy_list_for_config_read() and are not used by the new
|
||||||
@ -1204,6 +1465,12 @@ sweep_proxy_list(void)
|
|||||||
void
|
void
|
||||||
pt_free_all(void)
|
pt_free_all(void)
|
||||||
{
|
{
|
||||||
|
if (transport_list) {
|
||||||
|
clear_transport_list();
|
||||||
|
smartlist_free(transport_list);
|
||||||
|
transport_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (managed_proxy_list) {
|
if (managed_proxy_list) {
|
||||||
/* If the proxy is in PT_PROTO_COMPLETED, it has registered its
|
/* If the proxy is in PT_PROTO_COMPLETED, it has registered its
|
||||||
transports and it's the duty of the circuitbuild.c subsystem to
|
transports and it's the duty of the circuitbuild.c subsystem to
|
||||||
|
@ -11,6 +11,30 @@
|
|||||||
#ifndef TOR_TRANSPORTS_H
|
#ifndef TOR_TRANSPORTS_H
|
||||||
#define 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,
|
void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv,
|
||||||
int is_server);
|
int is_server);
|
||||||
|
|
||||||
@ -23,6 +47,8 @@ void pt_configure_remaining_proxies(void);
|
|||||||
|
|
||||||
int pt_proxies_configuration_pending(void);
|
int pt_proxies_configuration_pending(void);
|
||||||
|
|
||||||
|
char *pt_get_extra_info_descriptor_string(void);
|
||||||
|
|
||||||
void pt_free_all(void);
|
void pt_free_all(void);
|
||||||
|
|
||||||
void pt_prepare_proxy_list_for_config_read(void);
|
void pt_prepare_proxy_list_for_config_read(void);
|
||||||
@ -68,28 +94,7 @@ typedef struct {
|
|||||||
smartlist_t *transports_to_launch;
|
smartlist_t *transports_to_launch;
|
||||||
|
|
||||||
/* The 'transports' list contains all the transports this proxy has
|
/* The 'transports' list contains all the transports this proxy has
|
||||||
launched.
|
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 *).
|
|
||||||
*/
|
|
||||||
smartlist_t *transports;
|
smartlist_t *transports;
|
||||||
} managed_proxy_t;
|
} managed_proxy_t;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user