IBR-DTNSuite
0.8
|
00001 /* 00002 * Clock.cpp 00003 * 00004 * Created on: 24.06.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "ibrdtn/utils/Clock.h" 00009 #include "ibrdtn/data/AgeBlock.h" 00010 00011 #include <ibrcommon/Logger.h> 00012 00013 namespace dtn 00014 { 00015 namespace utils 00016 { 00017 int Clock::timezone = 0; 00018 float Clock::quality = 0; 00019 bool Clock::badclock = false; 00020 00021 struct timeval Clock::_offset; 00022 bool Clock::_offset_init = false; 00023 00024 bool Clock::modify_clock = false; 00025 00029 u_int32_t Clock::TIMEVAL_CONVERSION = 946684800; 00030 00031 Clock::Clock() 00032 { 00033 } 00034 00035 Clock::~Clock() 00036 { 00037 } 00038 00039 size_t Clock::getExpireTime(const dtn::data::Bundle &b) 00040 { 00041 if ((b._timestamp == 0) || dtn::utils::Clock::badclock) 00042 { 00043 // use the AgeBlock to verify the age 00044 try { 00045 const dtn::data::AgeBlock &agebl = b.getBlock<const dtn::data::AgeBlock>(); 00046 size_t seconds_left = b._lifetime - agebl.getSeconds(); 00047 return getTime() + seconds_left; 00048 } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { }; 00049 } 00050 00051 return __getExpireTime(b._timestamp, b._lifetime); 00052 } 00053 00054 size_t Clock::getExpireTime(size_t timestamp, size_t lifetime) 00055 { 00056 return __getExpireTime(timestamp, lifetime); 00057 } 00058 00059 size_t Clock::getExpireTime(size_t lifetime) 00060 { 00061 return __getExpireTime(getTime(), lifetime); 00062 } 00063 00064 size_t Clock::__getExpireTime(size_t timestamp, size_t lifetime) 00065 { 00066 // if the quality of time is zero, return standard expire time 00067 if (Clock::quality == 0) return timestamp + lifetime; 00068 00069 // calculate sigma based on the quality of time and the original lifetime 00070 size_t sigma = lifetime * (1 - Clock::quality); 00071 00072 // expiration adjusted by quality of time 00073 return timestamp + lifetime + sigma; 00074 } 00075 00076 bool Clock::isExpired(const dtn::data::Bundle &b) 00077 { 00078 // use the AgeBlock to verify the age 00079 try { 00080 const dtn::data::AgeBlock &agebl = b.getBlock<const dtn::data::AgeBlock>(); 00081 return (b._lifetime < agebl.getSeconds()); 00082 } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { }; 00083 00084 return __isExpired(b._timestamp, b._lifetime); 00085 } 00086 00087 bool Clock::isExpired(size_t timestamp, size_t lifetime) 00088 { 00089 return __isExpired(timestamp, lifetime); 00090 } 00091 00092 bool Clock::__isExpired(size_t timestamp, size_t lifetime) 00093 { 00094 // if the quality of time is zero or the clock is bad, then never expire a bundle 00095 if ((Clock::quality == 0) || dtn::utils::Clock::badclock) return false; 00096 00097 // calculate sigma based on the quality of time and the original lifetime 00098 size_t sigma = lifetime * (1 - Clock::quality); 00099 00100 // expiration adjusted by quality of time 00101 if ( Clock::getTime() > (timestamp + lifetime + sigma)) return true; 00102 00103 return false; 00104 } 00105 00106 size_t Clock::getTime() 00107 { 00108 struct timeval now; 00109 Clock::gettimeofday(&now); 00110 00111 // timezone 00112 int offset = Clock::timezone * 3600; 00113 00114 // do we believe we are before the year 2000? 00115 if ((u_int)now.tv_sec < TIMEVAL_CONVERSION) 00116 { 00117 return 0; 00118 } 00119 00120 return (now.tv_sec - TIMEVAL_CONVERSION) + offset; 00121 } 00122 00123 size_t Clock::getUnixTimestamp() 00124 { 00125 struct timeval now; 00126 Clock::gettimeofday(&now); 00127 00128 // timezone 00129 int offset = Clock::timezone * 3600; 00130 00131 return now.tv_sec + offset; 00132 } 00133 00134 void Clock::setOffset(struct timeval &tv) 00135 { 00136 if (!modify_clock) 00137 { 00138 if (!Clock::_offset_init) 00139 { 00140 timerclear(&Clock::_offset); 00141 Clock::_offset_init = true; 00142 } 00143 timeradd(&Clock::_offset, &tv, &Clock::_offset); 00144 IBRCOMMON_LOGGER(info) << "[Clock] new local offset: " << _offset.tv_sec << " seconds and " << _offset.tv_usec << " microseconds" << IBRCOMMON_LOGGER_ENDL; 00145 } 00146 else 00147 { 00148 struct timezone tz; 00149 struct timeval now; 00150 ::gettimeofday(&now, &tz); 00151 00152 // adjust by the offset 00153 timersub(&now, &tv, &now); 00154 00155 // set the local clock to the new timestamp 00156 ::settimeofday(&now, &tz); 00157 } 00158 } 00159 00160 void Clock::settimeofday(struct timeval *tv) 00161 { 00162 struct timezone tz; 00163 struct timeval now; 00164 ::gettimeofday(&now, &tz); 00165 00166 if (!modify_clock) 00167 { 00168 if (!Clock::_offset_init) 00169 { 00170 timerclear(&Clock::_offset); 00171 Clock::_offset_init = true; 00172 } 00173 timersub(&now, tv, &Clock::_offset); 00174 IBRCOMMON_LOGGER(info) << "[Clock] new local offset: " << _offset.tv_sec << " seconds and " << _offset.tv_usec << " microseconds" << IBRCOMMON_LOGGER_ENDL; 00175 } 00176 else 00177 { 00178 // set the local clock to the new timestamp 00179 ::settimeofday(tv, &tz); 00180 } 00181 } 00182 00183 void Clock::gettimeofday(struct timeval *tv) 00184 { 00185 struct timezone tz; 00186 ::gettimeofday(tv, &tz); 00187 00188 // correct by the local offset 00189 if (!modify_clock) 00190 { 00191 if (!Clock::_offset_init) 00192 { 00193 timerclear(&Clock::_offset); 00194 Clock::_offset_init = true; 00195 } 00196 // add offset 00197 timersub(tv, &Clock::_offset, tv); 00198 } 00199 } 00200 } 00201 }