diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | doc/TODO | 8 | ||||
-rw-r--r-- | doc/control-spec.txt | 10 | ||||
-rw-r--r-- | src/or/control.c | 49 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 17 |
6 files changed, 80 insertions, 9 deletions
@@ -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 @@ -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]; |