diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-07-11 17:20:22 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-07-11 17:20:22 +0000 |
commit | 658e1196d0ac44af1190b36b78a700654c4f2609 (patch) | |
tree | 2bc90b888403c26f0b308b39ab0bd2b55347d9d4 | |
parent | e1db33971e56949c5021185c3c156fde37a016d8 (diff) | |
download | tor-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.c | 140 |
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 |