IBR-DTN  1.0.0
Clock.cpp
Go to the documentation of this file.
1 /*
2  * Clock.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "ibrdtn/config.h"
23 #include "ibrdtn/utils/Clock.h"
24 #include "ibrdtn/data/AgeBlock.h"
25 #include "ibrdtn/data/MetaBundle.h"
26 
27 #include <ibrcommon/Logger.h>
28 #include <iomanip>
29 
30 namespace dtn
31 {
32  namespace utils
33  {
34  double Clock::_rating = 1.0;
35 
36  struct timeval Clock::_offset = Clock::__initialize_clock();
37  struct timeval Clock::__clock_reference = Clock::__get_clock_reference();
38 
39  bool Clock::_modify_clock = false;
40 
45 
49  struct timespec Clock::_uptime_reference = Clock::__get_monotonic_ts();
50 
51  Clock::Clock()
52  {
53  }
54 
55  Clock::~Clock()
56  {
57  }
58 
60  {
61  return _rating;
62  }
63 
64  void Clock::setRating(double val)
65  {
66  _rating = val;
67 
68  // debug quality of time
69  IBRCOMMON_LOGGER_DEBUG_TAG("Clock", 25) << "new clock rating is " << std::setprecision(16) << val << IBRCOMMON_LOGGER_ENDL;
70  }
71 
73  {
74  return _modify_clock;
75  }
76 
77  void Clock::setModifyClock(bool val)
78  {
79  struct timeval tv;
80 
81  // retrieve assumed clock
82  gettimeofday(&tv);
83 
84  // switch clock mode
85  _modify_clock = val;
86 
87  // set clock initially
88  settimeofday(&tv);
89  }
90 
92  {
93  if (b.timestamp == 0)
94  {
95  try {
96  // use the AgeBlock to verify the age
97  const dtn::data::AgeBlock &agebl = b.find<dtn::data::AgeBlock>();
98  dtn::data::Number seconds_left = 0;
99  if (b.lifetime > agebl.getSeconds()) {
100  seconds_left = b.lifetime - agebl.getSeconds();
101  }
102  return getTime() + seconds_left;
104  // if there is no AgeBlock this bundle is not valid
105  return 0;
106  }
107  }
108 
109  return __getExpireTime(b.timestamp, b.lifetime);
110  }
111 
113  {
114  return __getExpireTime(timestamp, lifetime);
115  }
116 
118  {
119  return __getExpireTime(getTime(), lifetime);
120  }
121 
122  dtn::data::Number Clock::__getExpireTime(const dtn::data::Timestamp &timestamp, const dtn::data::Number &lifetime)
123  {
124  // if our own clock or the bundles timestamp is invalid use the current timestamp
125  if ((getRating() == 0.0) || timestamp == 0) return getTime() + lifetime;
126 
127  return timestamp + lifetime;
128  }
129 
131  {
132  if (b.timestamp == 0)
133  {
134  // use the AgeBlock to verify the age
135  try {
136  const dtn::data::AgeBlock &agebl = b.find<dtn::data::AgeBlock>();
137  return (b.lifetime < agebl.getSeconds());
139  // if there is no AgeBlock this bundle is not valid
140  return true;
141  }
142  }
143 
144  return isExpired(b.timestamp, b.lifetime);
145  }
146 
148  {
149  // expiration adjusted by quality of time
150  if ( Clock::getTime() > m.expiretime ) return true;
151 
152  return false;
153  }
154 
155  bool Clock::isExpired(const dtn::data::Timestamp &timestamp, const dtn::data::Number &lifetime)
156  {
157  // can not check invalid timestamp
158  // assume bundle has an age block and trust on later checks
159  if (timestamp == 0) return false;
160 
161  // disable expiration if clock rating is too bad
162  if (getRating() == 0.0) return false;
163 
164  return Clock::getTime() > __getExpireTime(timestamp, lifetime);
165  }
166 
168  {
169  struct timeval now;
171 
172  return now.tv_sec;
173  }
174 
176  {
177  struct timespec ts;
178  ibrcommon::MonotonicClock::gettime(ts);
179  return dtn::data::Timestamp(ts.tv_sec);
180  }
181 
182  const struct timeval& Clock::getOffset()
183  {
184  return Clock::_offset;
185  }
186 
187  void Clock::setOffset(const struct timeval &tv)
188  {
189  // do not modify time on reference nodes
190  if (Clock::getRating() == 1.0) return;
191 
193  {
194  timeradd(&Clock::_offset, &tv, &Clock::_offset);
195  IBRCOMMON_LOGGER_TAG("Clock", info) << "new local offset: " << Clock::toDouble(_offset) << "s" << IBRCOMMON_LOGGER_ENDL;
196  }
197  else
198  {
199  struct timezone tz;
200  struct timeval now;
201  ::gettimeofday(&now, &tz);
202 
203  // adjust by the offset
204  timersub(&now, &tv, &now);
205 
206 #ifndef __WIN32__
207  // set the local clock to the new timestamp
208  ::settimeofday(&now, &tz);
209 #endif
210  }
211  }
212 
213  void Clock::settimeofday(struct timeval *tv)
214  {
215  struct timeval now;
216  struct timezone tz;
217 
218  // do not modify time on reference nodes
219  if (Clock::getRating() == 1.0) return;
220 
222  {
223  // get the monotonic time of day
224  __monotonic_gettimeofday(&now);
225 
226  // determine the new offset
227  timersub(&now, tv, &Clock::_offset);
228  }
229  else
230  {
231  // get the hosts time of day
232  ::gettimeofday(&now, &tz);
233 
234  // determine the new offset
235  timersub(&now, tv, &Clock::_offset);
236 
237 #ifndef __WIN32__
238  // set the local clock to the new timestamp
239  ::settimeofday(tv, &tz);
240 #endif
241  }
242 
243  IBRCOMMON_LOGGER_TAG("Clock", info) << "new local offset: " << Clock::toDouble(_offset) << "s" << IBRCOMMON_LOGGER_ENDL;
244  }
245 
246  void Clock::gettimeofday(struct timeval *tv)
247  {
248  if (!Clock::shouldModifyClock() && Clock::getRating() < 1.0)
249  {
250  // get the monotonic time of day
251  __monotonic_gettimeofday(tv);
252 
253  // add offset
254  timersub(tv, &Clock::_offset, tv);
255  }
256  else
257  {
258  struct timezone tz;
259  ::gettimeofday(tv, &tz);
260  }
261  }
262 
263  void Clock::getdtntimeofday(struct timeval *tv)
264  {
265  // query local time
267 
268  // do we believe we are before the year 2000?
269  if (dtn::data::Timestamp(tv->tv_sec) < TIMEVAL_CONVERSION)
270  {
271  tv->tv_sec = 0;
272  }
273  else
274  {
275  // do bundle protocol time conversion
276  tv->tv_sec -= TIMEVAL_CONVERSION.get<time_t>();
277  }
278  }
279 
280  double Clock::toDouble(const timeval &val) {
281  return static_cast<double>(val.tv_sec) + (static_cast<double>(val.tv_usec) / 1000000.0);
282  }
283 
285  {
286  struct timespec now;
287  struct timespec result;
288  ibrcommon::MonotonicClock::gettime(now);
289  ibrcommon::MonotonicClock::diff(_uptime_reference, now, result);
290 
291  return dtn::data::Timestamp(result.tv_sec);
292  }
293 
294  struct timespec Clock::__get_monotonic_ts()
295  {
296  struct timespec ts;
297 
298  // initialize up-time reference
299  ibrcommon::MonotonicClock::gettime(ts);
300  return ts;
301  }
302 
303  struct timeval Clock::__get_clock_reference()
304  {
305  struct timezone tz;
306  struct timeval now, tv;
307 
308  ::gettimeofday(&now, &tz);
309  ibrcommon::MonotonicClock::gettime(tv);
310 
311  timersub(&now, &tv, &now);
312 
313  return now;
314  }
315 
316  void Clock::__monotonic_gettimeofday(struct timeval *tv)
317  {
318  // use boot-time as reference to stay independent from
319  // external clock adjustments
320  struct timeval mtv;
321  ibrcommon::MonotonicClock::gettime(mtv);
322 
323  // combine clock reference and current boot-time
324  timeradd(&__clock_reference, &mtv, tv);
325  }
326 
327  struct timeval Clock::__initialize_clock()
328  {
329  struct timeval ret;
330  timerclear(&ret);
331  return ret;
332 
333  }
334  }
335 }
static void setModifyClock(bool val)
Definition: Clock.cpp:77
static const dtn::data::Timestamp TIMEVAL_CONVERSION
Definition: Clock.h:154
static void settimeofday(struct timeval *tv)
Definition: Clock.cpp:213
dtn::data::Timestamp timestamp
Definition: BundleID.h:54
dtn::data::Number getSeconds() const
Definition: AgeBlock.cpp:56
static void gettimeofday(struct timeval *tv)
Definition: Clock.cpp:246
static dtn::data::Timestamp getExpireTime(const dtn::data::Bundle &b)
Definition: Clock.cpp:91
static bool shouldModifyClock()
Definition: Clock.cpp:72
static void setOffset(const struct timeval &tv)
Definition: Clock.cpp:187
T get() const
Definition: SDNV.h:113
static dtn::data::Timestamp getUptime()
Definition: Clock.cpp:284
static double toDouble(const timeval &val)
Definition: Clock.cpp:280
static dtn::data::Timestamp getTime()
Definition: Clock.cpp:167
static const struct timeval & getOffset()
Definition: Clock.cpp:182
static double getRating()
Definition: Clock.cpp:59
static void setRating(double val)
Definition: Clock.cpp:64
iterator find(block_t blocktype)
Definition: Bundle.cpp:307
static dtn::data::Timestamp getMonotonicTimestamp()
Definition: Clock.cpp:175
static bool isExpired(const dtn::data::Timestamp &timestamp, const dtn::data::Number &lifetime)
Definition: Clock.cpp:155
dtn::data::SDNV< Size > Timestamp
Definition: Number.h:41
static void getdtntimeofday(struct timeval *tv)
Definition: Clock.cpp:263