Merge remote-tracking branch 'neel/b25511-r4'

This commit is contained in:
Nick Mathewson 2018-04-23 09:13:24 -04:00
commit cd3fc2aa48
8 changed files with 106 additions and 3 deletions

5
changes/ticket25511 Normal file
View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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",

View File

@ -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) */

View File

@ -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
};