Home | History | Annotate | Download | only in net
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/net/shill_time.h"
     18 
     19 #include <string.h>
     20 #include <time.h>
     21 
     22 #include <base/format_macros.h>
     23 #include <base/strings/stringprintf.h>
     24 
     25 using std::string;
     26 
     27 namespace shill {
     28 
     29 namespace {
     30 
     31 // As Time may be instantiated by MemoryLogMessage during a callback of
     32 // AtExitManager, it needs to be a leaky singleton to avoid
     33 // AtExitManager::RegisterCallback() from potentially being called within a
     34 // callback of AtExitManager, which will lead to a crash. Making Time leaky is
     35 // fine as it does not need to clean up or release any resource at destruction.
     36 base::LazyInstance<Time>::Leaky g_time = LAZY_INSTANCE_INITIALIZER;
     37 
     38 }  // namespace
     39 
     40 Time::Time() { }
     41 
     42 Time::~Time() { }
     43 
     44 Time* Time::GetInstance() {
     45   return g_time.Pointer();
     46 }
     47 
     48 bool Time::GetSecondsMonotonic(time_t* seconds) {
     49   struct timeval now;
     50   if (GetTimeMonotonic(&now) < 0) {
     51     return false;
     52   } else {
     53     *seconds = now.tv_sec;
     54     return true;
     55   }
     56 }
     57 
     58 bool Time::GetSecondsBoottime(time_t* seconds) {
     59   struct timeval now;
     60   if (GetTimeBoottime(&now) < 0) {
     61     return false;
     62   } else {
     63     *seconds = now.tv_sec;
     64     return true;
     65   }
     66 }
     67 
     68 int Time::GetTimeMonotonic(struct timeval* tv) {
     69   struct timespec ts;
     70   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
     71     return -1;
     72   }
     73 
     74   tv->tv_sec = ts.tv_sec;
     75   tv->tv_usec = ts.tv_nsec / 1000;
     76   return 0;
     77 }
     78 
     79 int Time::GetTimeBoottime(struct timeval* tv) {
     80   struct timespec ts;
     81   if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
     82     return -1;
     83   }
     84 
     85   tv->tv_sec = ts.tv_sec;
     86   tv->tv_usec = ts.tv_nsec / 1000;
     87   return 0;
     88 }
     89 
     90 int Time::GetTimeOfDay(struct timeval* tv, struct timezone* tz) {
     91   return gettimeofday(tv, tz);
     92 }
     93 
     94 Timestamp Time::GetNow() {
     95   struct timeval now_monotonic = {};
     96   struct timeval now_boottime = {};
     97   struct timeval now_wall_clock = {};
     98   struct tm local_time = {};
     99   string wall_clock_string;
    100 
    101   GetTimeMonotonic(&now_monotonic);
    102   GetTimeBoottime(&now_boottime);
    103   GetTimeOfDay(&now_wall_clock, nullptr);
    104   localtime_r(&now_wall_clock.tv_sec, &local_time);
    105   wall_clock_string = FormatTime(local_time, now_wall_clock.tv_usec);
    106 
    107   return Timestamp(now_monotonic, now_boottime, wall_clock_string);
    108 }
    109 
    110 // static
    111 string Time::FormatTime(const struct tm& date_time, suseconds_t usec) {
    112   char date_time_string[64];
    113   size_t date_time_length;
    114   date_time_length = strftime(date_time_string, sizeof(date_time_string),
    115                               "%Y-%m-%dT%H:%M:%S %z", &date_time);
    116 
    117   // Stitch in the microseconds, to provider finer resolution than
    118   // strftime allows.
    119   string full_string = "<unknown>";
    120   char* split_pos = static_cast<char*>(
    121       memchr(date_time_string, ' ', sizeof(date_time_string)));
    122   if (date_time_length && date_time_length < sizeof(date_time_string) &&
    123       split_pos) {
    124     *split_pos = '\0';
    125     full_string =
    126         base::StringPrintf("%s.%06" PRIu64 "%s", date_time_string,
    127                            static_cast<uint64_t>(usec), split_pos + 1);
    128   }
    129 
    130   return full_string;
    131 }
    132 
    133 time_t Time::GetSecondsSinceEpoch() const {
    134   return time(nullptr);
    135 }
    136 
    137 }  // namespace shill
    138