summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-07-11 17:20:22 +0000
committerNick Mathewson <nickm@torproject.org>2005-07-11 17:20:22 +0000
commit658e1196d0ac44af1190b36b78a700654c4f2609 (patch)
tree2bc90b888403c26f0b308b39ab0bd2b55347d9d4
parente1db33971e56949c5021185c3c156fde37a016d8 (diff)
downloadtor-658e1196d0ac44af1190b36b78a700654c4f2609.tar.gz
tor-658e1196d0ac44af1190b36b78a700654c4f2609.zip
Change retry_listeners: when force is false, close and re-open a minimal set of listeners (i.e., those that do not match the configuration). This fixes a possible bug on some windowses. Maybe.
svn:r4528
-rw-r--r--src/or/connection.c140
1 files changed, 74 insertions, 66 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index 06464c9e84..21cdf2a447 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -508,6 +508,8 @@ connection_create_listener(const char *bindaddress, uint16_t bindport, int type)
conn = connection_new(type);
conn->s = s;
+ conn->address = tor_strdup(bindaddress);
+ conn->port = usePort;
if (connection_add(conn) < 0) { /* no space, forget it */
log_fn(LOG_WARN,"connection_add failed. Giving up.");
@@ -759,29 +761,6 @@ connection_connect(connection_t *conn, char *address,
return 1;
}
-/** If there exist any listeners of type <b>type</b> in the connection
- * array, mark them for close.
- */
-static void
-listener_close_if_present(int type)
-{
- connection_t *conn;
- connection_t **carray;
- int i,n;
- tor_assert(type == CONN_TYPE_OR_LISTENER ||
- type == CONN_TYPE_AP_LISTENER ||
- type == CONN_TYPE_DIR_LISTENER ||
- type == CONN_TYPE_CONTROL_LISTENER);
- get_connection_array(&carray,&n);
- for (i=0;i<n;i++) {
- conn = carray[i];
- if (conn->type == type && !conn->marked_for_close) {
- connection_close_immediate(conn);
- connection_mark_for_close(conn);
- }
- }
-}
-
/**
* Launch any configured listener connections of type <b>type</b>. (A
* listener is configured if <b>port_option</b> is non-zero. If any
@@ -791,61 +770,90 @@ listener_close_if_present(int type)
*
* If <b>force</b> is true, close and re-open all listener connections.
* Otherwise, only relaunch the listeners of this type if the number of
- * existing connections is not as configured (e.g., because one died).
+ * existing connections is not as configured (e.g., because one died),
+ * or if the existing connections do not match those configured.
*/
static int
retry_listeners(int type, struct config_line_t *cfg,
int port_option, const char *default_addr, int force)
{
- if (!force) {
- int want, have, n_conn, i;
- struct config_line_t *c;
- connection_t *conn;
- connection_t **carray;
- /* How many should there be? */
- if (cfg && port_option) {
- want = 0;
- for (c = cfg; c; c = c->next)
- ++want;
- } else if (port_option) {
- want = 1;
- } else {
- want = 0;
- }
+ struct smartlist_t *launch = smartlist_create();
+ int free_launch_elts = 1;
+ struct config_line_t *c;
+ int n_conn, i;
+ connection_t *conn;
+ connection_t **carray;
+ struct config_line_t *line;
- /* How many are there actually? */
- have = 0;
- get_connection_array(&carray,&n_conn);
- for (i=0;i<n_conn;i++) {
- conn = carray[i];
- if (conn->type == type && !conn->marked_for_close)
- ++have;
+ if (cfg && port_option) {
+ for (c = cfg; c; c = c->next) {
+ smartlist_add(launch, c);
}
-
- /* If we have the right number of listeners, do nothing. */
- if (have == want)
- return 0;
-
- /* Otherwise, warn the user and relaunch. */
- log_fn(LOG_NOTICE,"We have %d %s(s) open, but we want %d; relaunching.",
- have, conn_type_to_string(type), want);
+ free_launch_elts = 0;
+ } else if (port_option) {
+ line = tor_malloc_zero(sizeof(struct config_line_t));
+ line->key = tor_strdup("");
+ line->value = tor_strdup(default_addr);
+ smartlist_add(launch, line);
}
- listener_close_if_present(type);
- if (port_option) {
- if (!cfg) {
- if (connection_create_listener(default_addr, (uint16_t) port_option,
- type)<0)
- return -1;
+ get_connection_array(&carray,&n_conn);
+ for (i=0; i < n_conn; ++i) {
+ conn = carray[i];
+ if (conn->type != type || conn->marked_for_close)
+ continue;
+ if (force) {
+ /* It's a listener, and we're relaunching all listeners of this
+ * type. Close this one. */
+ log_fn(LOG_NOTICE, "Closing listener on %s:%d", conn->address, conn->port);
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
+ continue;
+ }
+ /* Okay, so this is a listener. Is it configured? */
+ line = NULL;
+ SMARTLIST_FOREACH(launch, struct config_line_t *, wanted,
+ {
+ char *addr;
+ uint16_t port;
+ if (! parse_addr_port(wanted->value, &addr, NULL, &port)) {
+ if (! port)
+ port = port_option;
+ if (port == conn->port && !strcasecmp(addr, conn->address)) {
+ line = wanted;
+ break;
+ }
+ }
+ });
+ if (! line) {
+ /* This one isn't configured. Close it. */
+ log_fn(LOG_NOTICE, "Closing listener on %s:%d", conn->address, conn->port);
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
} else {
- for ( ; cfg; cfg = cfg->next) {
- if (connection_create_listener(cfg->value, (uint16_t) port_option,
- type)<0)
- return -1;
- }
+ /* It's configured; we don't need to launch it. */
+ log_fn(LOG_INFO, "Already have listener on %s:%d",conn->address,conn->port);
+ smartlist_remove(launch, line);
}
}
- return 0;
+
+ /* Now open all the listeners that are configured but not opened. */
+ i = 0;
+ SMARTLIST_FOREACH(launch, struct config_line_t *, cfg,
+ {
+ log_fn(LOG_NOTICE, "Opening listener on %s:%d", cfg->value, port_option);
+ if (connection_create_listener(cfg->value, (uint16_t) port_option,
+ type)<0)
+ i = -1;
+ });
+
+ if (free_launch_elts) {
+ SMARTLIST_FOREACH(launch, struct config_line_t *, cfg,
+ config_free_lines(cfg));
+ }
+ smartlist_free(launch);
+
+ return i;
}
/** (Re)launch listeners for each port you should have open. If