IBR-DTNSuite  0.12
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;
37  bool Clock::_offset_init = false;
38 
39  bool Clock::_modify_clock = false;
40 
45 
49  ibrcommon::MonotonicClock Clock::_monotonic_clock;
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  _modify_clock = val;
80  }
81 
83  {
84  if (b.timestamp == 0)
85  {
86  try {
87  // use the AgeBlock to verify the age
88  const dtn::data::AgeBlock &agebl = b.find<dtn::data::AgeBlock>();
89  dtn::data::Number seconds_left = 0;
90  if (b.lifetime > agebl.getSeconds()) {
91  seconds_left = b.lifetime - agebl.getSeconds();
92  }
93  return getTime() + seconds_left;
95  // if there is no AgeBlock this bundle is not valid
96  return 0;
97  }
98  }
99 
100  return __getExpireTime(b.timestamp, b.lifetime);
101  }
102 
104  {
105  return __getExpireTime(timestamp, lifetime);
106  }
107 
109  {
110  return __getExpireTime(getTime(), lifetime);
111  }
112 
113  dtn::data::Number Clock::__getExpireTime(const dtn::data::Timestamp &timestamp, const dtn::data::Number &lifetime)
114  {
115  // if our own clock or the bundles timestamp is invalid use the current timestamp
116  if ((getRating() == 0.0) || timestamp == 0) return getTime() + lifetime;
117 
118  return timestamp + lifetime;
119  }
120 
122  {
123  if (b.timestamp == 0)
124  {
125  // use the AgeBlock to verify the age
126  try {
127  const dtn::data::AgeBlock &agebl = b.find<dtn::data::AgeBlock>();
128  return (b.lifetime < agebl.getSeconds());
130  // if there is no AgeBlock this bundle is not valid
131  return true;
132  }
133  }
134 
135  return isExpired(b.timestamp, b.lifetime);
136  }
137 
139  {
140  // expiration adjusted by quality of time
141  if ( Clock::getTime() > m.expiretime ) return true;
142 
143  return false;
144  }
145 
146  bool Clock::isExpired(const dtn::data::Timestamp &timestamp, const dtn::data::Number &lifetime)
147  {
148  // can not check invalid timestamp
149  // assume bundle has an age block and trust on later checks
150  if (timestamp == 0) return false;
151 
152  // disable expiration if clock rating is too bad
153  if (getRating() == 0.0) return false;
154 
155  return Clock::getTime() > __getExpireTime(timestamp, lifetime);
156  }
157 
159  {
160  struct timeval now;
162 
163  return now.tv_sec;
164  }
165 
167  {
168  return _monotonic_clock.getSeconds();
169  }
170 
171  const struct timeval& Clock::getOffset()
172  {
173  return Clock::_offset;
174  }
175 
176  void Clock::setOffset(const struct timeval &tv)
177  {
179  {
180  if (!Clock::_offset_init)
181  {
182  timerclear(&Clock::_offset);
183  Clock::_offset_init = true;
184  }
185 
186  timeradd(&Clock::_offset, &tv, &Clock::_offset);
187  IBRCOMMON_LOGGER_TAG("Clock", info) << "new local offset: " << Clock::toDouble(_offset) << "s" << IBRCOMMON_LOGGER_ENDL;
188  }
189  else
190  {
191  struct timezone tz;
192  struct timeval now;
193  ::gettimeofday(&now, &tz);
194 
195  // adjust by the offset
196  timersub(&now, &tv, &now);
197 
198 #ifndef __WIN32__
199  // set the local clock to the new timestamp
200  ::settimeofday(&now, &tz);
201 #endif
202  }
203  }
204 
205  void Clock::settimeofday(struct timeval *tv)
206  {
207  struct timezone tz;
208  struct timeval now;
209  ::gettimeofday(&now, &tz);
210 
212  {
213  if (!Clock::_offset_init)
214  {
215  timerclear(&Clock::_offset);
216  Clock::_offset_init = true;
217  }
218  timersub(&now, tv, &Clock::_offset);
219  IBRCOMMON_LOGGER_TAG("Clock", info) << "new local offset: " << Clock::toDouble(_offset) << "s" << IBRCOMMON_LOGGER_ENDL;
220  }
221  else
222  {
223 #ifndef __WIN32__
224  // set the local clock to the new timestamp
225  ::settimeofday(tv, &tz);
226 #endif
227  }
228  }
229 
230  void Clock::gettimeofday(struct timeval *tv)
231  {
232  struct timezone tz;
233  ::gettimeofday(tv, &tz);
234 
235  // correct by the local offset
237  {
238  if (!Clock::_offset_init)
239  {
240  timerclear(&Clock::_offset);
241  Clock::_offset_init = true;
242  }
243 
244  // add offset
245  timersub(tv, &Clock::_offset, tv);
246  }
247  }
248 
249  void Clock::getdtntimeofday(struct timeval *tv)
250  {
251  struct timezone tz;
252  ::gettimeofday(tv, &tz);
253 
254  // correct by the local offset
256  {
257  if (!Clock::_offset_init)
258  {
259  timerclear(&Clock::_offset);
260  Clock::_offset_init = true;
261  }
262 
263  // add offset
264  timersub(tv, &Clock::_offset, tv);
265  }
266 
267  // do we believe we are before the year 2000?
268  if (dtn::data::Timestamp(tv->tv_sec) < TIMEVAL_CONVERSION)
269  {
270  tv->tv_sec = 0;
271  }
272  else
273  {
274  // do bundle protocol time conversion
275  tv->tv_sec -= TIMEVAL_CONVERSION.get<time_t>();
276  }
277  }
278 
279  double Clock::toDouble(const timeval &val) {
280  return static_cast<double>(val.tv_sec) + (static_cast<double>(val.tv_usec) / 1000000.0);
281  }
282 
284  {
286  }
287  }
288 }