diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-04-23 09:13:24 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-04-23 09:13:24 -0400 |
commit | cd3fc2aa4867e89877bbfb99f4f767d761b91f25 (patch) | |
tree | 5ff12068373e17f8218907d153f67b6c8c9fcc26 | |
parent | 8c01aee2e3b8970af96f5b1a662bdf80d0e22489 (diff) | |
parent | dca36eff8fbe9307aa2f74d26841399537e11406 (diff) | |
download | tor-cd3fc2aa4867e89877bbfb99f4f767d761b91f25.tar.gz tor-cd3fc2aa4867e89877bbfb99f4f767d761b91f25.zip |
Merge remote-tracking branch 'neel/b25511-r4'
-rw-r--r-- | changes/ticket25511 | 5 | ||||
-rw-r--r-- | src/common/compat_time.c | 4 | ||||
-rw-r--r-- | src/common/compat_time.h | 2 | ||||
-rw-r--r-- | src/common/util.c | 9 | ||||
-rw-r--r-- | src/common/util.h | 1 | ||||
-rw-r--r-- | src/or/control.c | 28 | ||||
-rw-r--r-- | src/or/control.h | 4 | ||||
-rw-r--r-- | src/test/test_controller.c | 56 |
8 files changed, 106 insertions, 3 deletions
diff --git a/changes/ticket25511 b/changes/ticket25511 new file mode 100644 index 0000000000..0a24e265ca --- /dev/null +++ b/changes/ticket25511 @@ -0,0 +1,5 @@ + o Minor features (control port): + - Introduce GETINFO "current-time/{local,utc}" to return the local + and UTC times respectively in ISO format. This helps a controller + like Tor Browser detect a time-related error. Closes ticket 25511. + Patch by Neel Chauhan. diff --git a/src/common/compat_time.c b/src/common/compat_time.c index b940447b67..966216768f 100644 --- a/src/common/compat_time.c +++ b/src/common/compat_time.c @@ -71,8 +71,8 @@ tor_sleep_msec(int msec) /** Set *timeval to the current time of day. On error, log and terminate. * (Same as gettimeofday(timeval,NULL), but never returns -1.) */ -void -tor_gettimeofday(struct timeval *timeval) +MOCK_IMPL(void, +tor_gettimeofday, (struct timeval *timeval)) { #ifdef _WIN32 /* Epoch bias copied from perl: number of units between windows epoch and diff --git a/src/common/compat_time.h b/src/common/compat_time.h index 75b57f6f24..09dd6add3d 100644 --- a/src/common/compat_time.h +++ b/src/common/compat_time.h @@ -173,7 +173,7 @@ void monotime_coarse_add_msec(monotime_coarse_t *out, #define monotime_coarse_add_msec monotime_add_msec #endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */ -void tor_gettimeofday(struct timeval *timeval); +MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval)); #ifdef TOR_UNIT_TESTS void tor_sleep_msec(int msec); diff --git a/src/common/util.c b/src/common/util.c index b14b6f3979..53e4507f1f 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1834,6 +1834,15 @@ format_iso_time(char *buf, time_t t) strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm)); } +/** As format_local_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid + * embedding an internal space. */ +void +format_local_iso_time_nospace(char *buf, time_t t) +{ + format_local_iso_time(buf, t); + buf[10] = 'T'; +} + /** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid * embedding an internal space. */ void diff --git a/src/common/util.h b/src/common/util.h index c0d20e1b22..7172b7da08 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -271,6 +271,7 @@ int parse_rfc1123_time(const char *buf, time_t *t); #define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7) void format_local_iso_time(char *buf, time_t t); void format_iso_time(char *buf, time_t t); +void format_local_iso_time_nospace(char *buf, time_t t); void format_iso_time_nospace(char *buf, time_t t); void format_iso_time_nospace_usec(char *buf, const struct timeval *tv); int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace); diff --git a/src/or/control.c b/src/or/control.c index 6f56313eaa..dda8872182 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1931,6 +1931,31 @@ getinfo_helper_listeners(control_connection_t *control_conn, return 0; } +/** Implementation helper for GETINFO: answers requests for information about + * the current time in both local and UTF forms. */ +STATIC int +getinfo_helper_current_time(control_connection_t *control_conn, + const char *question, + char **answer, const char **errmsg) +{ + (void)control_conn; + (void)errmsg; + + struct timeval now; + tor_gettimeofday(&now); + char timebuf[ISO_TIME_LEN+1]; + + if (!strcmp(question, "current-time/local")) + format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec); + else if (!strcmp(question, "current-time/utc")) + format_iso_time_nospace(timebuf, (time_t)now.tv_sec); + else + return 0; + + *answer = tor_strdup(timebuf); + return 0; +} + /** Implementation helper for GETINFO: knows the answers for questions about * directory information. */ STATIC int @@ -3073,6 +3098,9 @@ static const getinfo_item_t getinfo_items[] = { DOC("config/defaults", "List of default values for configuration options. " "See also config/names"), + PREFIX("current-time/", current_time, "Current time."), + DOC("current-time/local", "Current time on the local system."), + DOC("current-time/utc", "Current UTC time."), PREFIX("downloads/networkstatus/", downloads, "Download statuses for networkstatus objects"), DOC("downloads/networkstatus/ns", diff --git a/src/or/control.h b/src/or/control.h index 2fd3c553f3..2f312a6638 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -311,6 +311,10 @@ STATIC int getinfo_helper_dir( control_connection_t *control_conn, const char *question, char **answer, const char **errmsg); +STATIC int getinfo_helper_current_time( + control_connection_t *control_conn, + const char *question, char **answer, + const char **errmsg); #endif /* defined(CONTROL_PRIVATE) */ diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 1c285bb3a2..3b58a78e1d 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -1470,6 +1470,61 @@ test_download_status_bridge(void *arg) return; } +/** Set timeval to a mock date and time. This is neccessary + * to make tor_gettimeofday() mockable. */ +static void +mock_tor_gettimeofday(struct timeval *timeval) +{ + timeval->tv_sec = 1523405073; + timeval->tv_usec = 271645; +} + +static void +test_current_time(void *arg) +{ + /* We just need one of these to pass, it doesn't matter what's in it */ + control_connection_t dummy; + /* Get results out */ + char *answer = NULL; + const char *errmsg = NULL; + + (void)arg; + + /* We need these for storing the (mock) time. */ + MOCK(tor_gettimeofday, mock_tor_gettimeofday); + struct timeval now; + tor_gettimeofday(&now); + char timebuf[ISO_TIME_LEN+1]; + + /* Case 1 - local time */ + format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec); + getinfo_helper_current_time(&dummy, + "current-time/local", + &answer, &errmsg); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); + tt_str_op(answer, OP_EQ, timebuf); + tor_free(answer); + errmsg = NULL; + + /* Case 2 - UTC time */ + format_iso_time_nospace(timebuf, (time_t)now.tv_sec); + getinfo_helper_current_time(&dummy, + "current-time/utc", + &answer, &errmsg); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); + tt_str_op(answer, OP_EQ, timebuf); + tor_free(answer); + errmsg = NULL; + + done: + UNMOCK(tor_gettimeofday); + tor_free(answer); + + return; +} + struct testcase_t controller_tests[] = { { "add_onion_helper_keyarg_v2", test_add_onion_helper_keyarg_v2, 0, NULL, NULL }, @@ -1486,6 +1541,7 @@ struct testcase_t controller_tests[] = { NULL }, { "download_status_desc", test_download_status_desc, 0, NULL, NULL }, { "download_status_bridge", test_download_status_bridge, 0, NULL, NULL }, + { "current_time", test_current_time, 0, NULL, NULL }, END_OF_TESTCASES }; |