aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--doc/TODO8
-rw-r--r--doc/control-spec.txt10
-rw-r--r--src/or/control.c49
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/routerlist.c17
6 files changed, 80 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b18c0904..41c3267ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -24,6 +24,8 @@ Changes in version 0.1.2.3-alpha - 2006-10-??
about the current state of a router.
- Stream events also have REASON and REMOTE_REASON fields, working much
like those for circuit events.
+ - NS events to inform a controller when our opinion of a router's status
+ has changed.
o Security bugfixes:
- When the user sends a NEWNYM signal, clear the client-side DNS
diff --git a/doc/TODO b/doc/TODO
index 7c257c0ae..0b429308b 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -79,9 +79,11 @@ d - Tolerate clock skew on bridge relays.
o A way to examine router flags from controller.
o Specify: GETINFO ns/id/x, ns/name/x, ns/all.
o Implement
-N - A way to alert controller when router flags change.
- - Specify: SETEVENTS NS
- - Implement
+ o A way to alert controller when router flags change.
+ o Specify: SETEVENTS NS
+ o Implement
+N - Hunt for places that change networkstatus info that I might have
+ missed.
d - A way to adjust router flags from the controller
d - a way to pick entries based wholly on extend_info equivalent;
a way to export extend_info equivalent.
diff --git a/doc/control-spec.txt b/doc/control-spec.txt
index 49e81995a..8ded5448e 100644
--- a/doc/control-spec.txt
+++ b/doc/control-spec.txt
@@ -194,7 +194,8 @@ $Id$
EventCode = "CIRC" / "STREAM" / "ORCONN" / "BW" / "DEBUG" /
"INFO" / "NOTICE" / "WARN" / "ERR" / "NEWDESC" / "ADDRMAP" /
"AUTHDIR_NEWDESCS" / "DESCCHANGED" / "STATUS_GENERAL" /
- "STATUS_CLIENT" / "STATUS_SERVER" / "GUARDS"
+ "STATUS_CLIENT" / "STATUS_SERVER" / "GUARDS" / "NS" /
+ "NS_FULL"
Any events *not* listed in the SETEVENTS line are turned off; thus, sending
SETEVENTS with an empty body turns off all event reporting.
@@ -1085,6 +1086,13 @@ $Id$
...
[needs to be fleshed out; not implemented yet]
+4.1.12. Network status has changed
+
+ Syntax:
+ "650" "+" "NS" CRLF 1*NetworkStatus "." CRLF
+
+ [First added in 0.1.2.3-alpha]
+
5. Implementation notes
5.1. Authentication
diff --git a/src/or/control.c b/src/or/control.c
index 05b2da2ee..eb68497c3 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -82,7 +82,9 @@ const char control_c_id[] =
#define EVENT_ADDRMAP 0x000C
#define EVENT_AUTHDIR_NEWDESCS 0x000D
#define EVENT_DESCCHANGED 0x000E
-#define _EVENT_MAX 0x000E
+#define EVENT_NS 0x000F
+#define _EVENT_MAX 0x000F
+/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */
/** Array mapping from message type codes to human-readable message
* type names. Used for compatibility with version 0 of the control
@@ -1050,6 +1052,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
event_code = EVENT_AUTHDIR_NEWDESCS;
else if (!strcasecmp(ev, "DESCCHANGED"))
event_code = EVENT_DESCCHANGED;
+ else if (!strcasecmp(ev, "NS"))
+ event_code = EVENT_NS;
else {
connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
ev);
@@ -3347,6 +3351,49 @@ control_event_or_authdir_new_descriptor(const char *action,
return 0;
}
+/* DOCDOC takes a list of local_routerstatus_t */
+int
+control_event_networkstatus_changed(smartlist_t *statuses)
+{
+ smartlist_t *strs;
+ char *s;
+ if (!EVENT_IS_INTERESTING(EVENT_NS) || !smartlist_len(statuses))
+ return 0;
+
+ strs = smartlist_create();
+ smartlist_add(strs, tor_strdup("650+NS\r\n"));
+ SMARTLIST_FOREACH(statuses, local_routerstatus_t *, rs,
+ {
+ s = networkstatus_getinfo_helper_single(&rs->status);
+ if (!s) continue;
+ smartlist_add(strs, s);
+ });
+ smartlist_add(strs, tor_strdup("\r\n.\r\n"));
+
+ s = smartlist_join_strings(strs, "", 0, NULL);
+ SMARTLIST_FOREACH(strs, char *, cp, tor_free(cp));
+ smartlist_free(strs);
+ send_control1_event_string(EVENT_NS, ALL_NAMES|ALL_FORMATS, s);
+ tor_free(s);
+ return 0;
+}
+
+int
+control_event_networkstatus_changed_single(local_routerstatus_t *rs)
+{
+ smartlist_t *statuses;
+ int r;
+
+ if (!EVENT_IS_INTERESTING(EVENT_NS))
+ return 0;
+
+ statuses = smartlist_create();
+ smartlist_add(statuses, rs);
+ r = control_event_networkstatus_changed(statuses);
+ smartlist_free(statuses);
+ return r;
+}
+
/** Our own router descriptor has changed; tell any controllers that care.
*/
int
diff --git a/src/or/or.h b/src/or/or.h
index 1909bd811..0550be302 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2115,6 +2115,8 @@ int control_event_or_authdir_new_descriptor(const char *action,
const char *descriptor,
const char *msg);
int control_event_my_descriptor_changed(void);
+int control_event_networkstatus_changed(smartlist_t *statuses);
+int control_event_networkstatus_changed_single(local_routerstatus_t *rs);
int init_cookie_authentication(int enabled);
int decode_hashed_password(char *buf, const char *hashed);
@@ -2682,6 +2684,7 @@ void router_reset_status_download_failures(void);
int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
const char *esc_router_info(routerinfo_t *router);
+char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
int networkstatus_getinfo_helper(const char *question, char **answer);
/********************************* routerparse.c ************************/
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index ea5d90fb4..9e4fce437 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -606,8 +606,10 @@ mark_all_trusteddirservers_up(void)
dir->is_running = 1;
dir->n_networkstatus_failures = 0;
rs = router_get_combined_status_by_digest(dir->digest);
- if (rs)
+ if (rs && !rs->status.is_running) {
rs->status.is_running = 1;
+ control_event_networkstatus_changed_single(rs);
+ }
});
}
last_networkstatus_download_attempted = 0;
@@ -1670,8 +1672,9 @@ router_set_status(const char *digest, int up)
router->is_running = up;
}
status = router_get_combined_status_by_digest(digest);
- if (status) {
+ if (status && status->status.is_running != up) {
status->status.is_running = up;
+ control_event_networkstatus_changed_single(status);
}
router_dir_info_changed();
}
@@ -3187,7 +3190,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
int i, j, warned;
int *index, *size;
networkstatus_t **networkstatus;
- smartlist_t *result;
+ smartlist_t *result, *changed_list;
strmap_t *name_map;
char conflict[DIGEST_LEN]; /* Sentinel value */
desc_digest_count_t *digest_counts = NULL;
@@ -3287,6 +3290,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
}
result = smartlist_create();
+ changed_list = smartlist_create();
digest_counts = tor_malloc_zero(sizeof(desc_digest_count_t)*n_statuses);
/* Iterate through all of the sorted routerstatus lists in lockstep.
@@ -3439,6 +3443,8 @@ routerstatus_list_update_from_networkstatus(time_t now)
rs_out->status.is_stable = n_stable > n_statuses/2;
rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2;
rs_out->status.is_bad_exit = n_bad_exit > n_listing_bad_exits/2;
+ if (!rs_old || memcmp(rs_old, rs_out, sizeof(local_routerstatus_t)))
+ smartlist_add(changed_list, rs_out);
}
SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
local_routerstatus_free(rs));
@@ -3454,6 +3460,9 @@ routerstatus_list_update_from_networkstatus(time_t now)
networkstatus_list_has_changed = 0;
routerstatus_list_has_changed = 1;
+
+ control_event_networkstatus_changed(changed_list);
+ smartlist_free(changed_list);
}
/** Given a list <b>routers</b> of routerinfo_t *, update each routers's
@@ -4113,7 +4122,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
* return the result in a newly allocated string. Used only by controller
* interface (for now.) */
/* XXXX This should eventually merge into generate_v2_networkstatus() */
-static char *
+char *
networkstatus_getinfo_helper_single(routerstatus_t *rs)
{
char buf[192];