}
static int retry_listeners(int type, struct config_line_t *cfg,
- int port_option, const char *default_addr)
+ 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;
+ }
+
+ /* 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 we have the right number of listeners, do nothing. */
+ if (have == want)
+ return 0;
+
+ /* Otherwise, warn the user and relaunch. */
+ log_fn(LOG_WARN,"We have %d %s(s) open, but we want %d; relaunching.",
+ have, conn_type_to_string[type], want);
+ }
+
listener_close_if_present(type);
if (port_option) {
if (!cfg) {
- if (connection_create_listener(default_addr, (uint16_t) port_option,
+ if (connection_create_listener(default_addr, (uint16_t) port_option,
type)<0)
return -1;
} else {
return 0;
}
-/** (Re)launch listeners for each port you should have open.
+/** (Re)launch listeners for each port you should have open. If
+ * <b>force</b> is true, close and relaunch all listeners. If <b>force</b>
+ * is false, then only relaunch listeners when we have the wrong number of
+ * connections for a given type.
*/
-int retry_all_listeners(void) {
+int retry_all_listeners(int force) {
if (retry_listeners(CONN_TYPE_OR_LISTENER, options.ORBindAddress,
- options.ORPort, "0.0.0.0")<0)
+ options.ORPort, "0.0.0.0", force)<0)
return -1;
if (retry_listeners(CONN_TYPE_DIR_LISTENER, options.DirBindAddress,
- options.DirPort, "0.0.0.0")<0)
+ options.DirPort, "0.0.0.0", force)<0)
return -1;
if (retry_listeners(CONN_TYPE_AP_LISTENER, options.SocksBindAddress,
- options.SocksPort, "127.0.0.1")<0)
+ options.SocksPort, "127.0.0.1", force)<0)
return -1;
return 0;
static long time_to_fetch_directory = 0;
static time_t last_uploaded_services = 0;
static time_t last_rotated_certificate = 0;
+ static time_t time_to_check_listeners = 0;
int i;
/** 0. See if we've been asked to shut down and our timeout has
*/
connection_expire_held_open();
+ /** 3d. And every 60 secionds, we relaunch listeners if any died. */
+ if (time_to_check_listeners < now) {
+ retry_all_listeners(0); /* 0 means "only if some died." */
+ time_to_check_listeners = now+60;
+ }
+
/** 4. Every second, we try a new circuit if there are no valid
* circuits. Every NewCircuitPeriod seconds, we expire circuits
* that became dirty more than NewCircuitPeriod seconds ago,
log_fn(LOG_ERR,"Error reloading rendezvous service keys");
return -1;
}
- if(retry_all_listeners() < 0) {
+ if(retry_all_listeners(1) < 0) {
log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
return -1;
}
}
/* start up the necessary listeners based on which ports are non-zero. */
- if(retry_all_listeners() < 0) {
+ if(retry_all_listeners(1) < 0) {
log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
return -1;
}