Merge remote-tracking branch 'neel/b25511-r4'
This commit is contained in:
commit
cd3fc2aa48
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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) */
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue