IBR-DTNSuite  0.12
DiscoveryAgent.cpp
Go to the documentation of this file.
1 /*
2  * DiscoveryAgent.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 "Configuration.h"
23 #include "net/DiscoveryAgent.h"
24 #include "net/DiscoveryService.h"
25 #include "net/DiscoveryBeacon.h"
26 #include "core/BundleCore.h"
27 #include "core/TimeEvent.h"
28 #include "core/NodeEvent.h"
29 #include "core/GlobalEvent.h"
30 #include "core/EventDispatcher.h"
31 #include <ibrdtn/utils/Utils.h>
32 #include <ibrdtn/utils/Clock.h>
33 #include <ibrcommon/Logger.h>
34 
35 using namespace dtn::core;
36 
37 namespace dtn
38 {
39  namespace net
40  {
41  DiscoveryAgent::DiscoveryAgent()
42  : _config(dtn::daemon::Configuration::getInstance().getDiscovery()),
43  _enabled(true), _sn(0), _adv_next(0), _last_announce_sent(0)
44  {
45  }
46 
48  {
49  }
50 
51  const std::string DiscoveryAgent::getName() const
52  {
53  return "DiscoveryAgent";
54  }
55 
56  void DiscoveryAgent::raiseEvent(const dtn::core::Event *evt) throw ()
57  {
58  try {
59  dynamic_cast<const dtn::core::TimeEvent&>(*evt);
61 
62  if (_config.announce() && (_adv_next <= ts)) {
63  // advertise me
64  onAdvertise();
65 
66  // next advertisement in one second
67  _adv_next = ts + 1;
68  }
69  } catch (const std::bad_cast&) {
70 
71  }
72 
73  try {
74  const dtn::core::GlobalEvent &global = dynamic_cast<const dtn::core::GlobalEvent&>(*evt);
76  // start sending discovery beacons
77  _enabled = true;
78  }
80  // suspend discovery beacons
81  _enabled = false;
82  }
83  } catch (const std::bad_cast&) {
84 
85  }
86  }
87 
89  {
90  // listen to global events (discovery start/stop)
92 
93  // listen to time events
95  }
96 
98  {
99  // un-listen to global events (discovery start/stop)
101 
102  // un-listen to time events
104  }
105 
107  {
108  ibrcommon::MutexLock l(_provider_lock);
109  handler_list &list = _providers[iface];
110  list.push_back(handler);
111  }
112 
114  {
115  ibrcommon::MutexLock l(_provider_lock);
116  handler_list &list = _providers[_any_iface];
117  list.push_back(handler);
118  }
119 
121  {
122  ibrcommon::MutexLock l(_provider_lock);
123 
124  // walk though all interfaces
125  for (handler_map::iterator it_p = _providers.begin(); it_p != _providers.end();)
126  {
127  handler_list &list = (*it_p).second;
128 
129  for (handler_list::iterator it = list.begin(); it != list.end(); ++it) {
130  if ((*it) == handler) {
131  list.erase(it);
132  break;
133  }
134  }
135 
136  if (list.empty())
137  _providers.erase(it_p++);
138  else
139  ++it_p;
140  }
141  }
142 
144  {
145  ibrcommon::MutexLock l(_provider_lock);
146  if (_providers.find(iface) == _providers.end()) return;
147 
148  handler_list &list = _providers[iface];
149 
150  for (handler_list::iterator it = list.begin(); it != list.end(); ++it) {
151  if ((*it) == handler) {
152  list.erase(it);
153  if (list.empty()) _providers.erase(iface);
154  return;
155  }
156  }
157  }
158 
160  {
162 
163  switch (_config.version())
164  {
165  case 2:
167  break;
168 
169  case 1:
171  break;
172 
173  case 0:
174  IBRCOMMON_LOGGER_TAG("DiscoveryAgent", info) << "DTN2 compatibility mode" << IBRCOMMON_LOGGER_ENDL;
176  break;
177  };
178 
180 
181  return beacon;
182  }
183 
185  {
186  // ignore own beacons
187  if (beacon.getEID() == dtn::core::BundleCore::local) return;
188 
189  // convert the announcement into NodeEvents
190  Node n(beacon.getEID());
191 
192  const std::list<DiscoveryService> &services = beacon.getServices();
193 
194  for (std::list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); ++iter)
195  {
196  const dtn::data::Number to_value = _config.timeout();
197 
198  const DiscoveryService &s = (*iter);
199 
200  // get protocol from tag
202 
204  {
205  // Set timeout
206  dtn::data::Number to_value_mailcl = to_value;
208  if(configTime > 0)
209  to_value_mailcl = configTime;
210 
211  n.add(Node::URI(Node::NODE_DISCOVERED, Node::CONN_EMAIL, s.getParameters(), to_value_mailcl, 20));
212  }
214  {
215  n.add(Node::Attribute(Node::NODE_DISCOVERED, s.getName(), s.getParameters(), to_value, 20));
216  }
217  else
218  {
219  n.add(Node::URI(Node::NODE_DISCOVERED, p, s.getParameters(), to_value, 20));
220  }
221  }
222 
223  // announce NodeInfo to ConnectionManager
225 
226  // if continuous announcements are disabled, then reply to this message
227  if (!_config.announce())
228  {
229  // first check if another announcement was sent during the same seconds
231 
232  if (_last_announce_sent != ts)
233  {
234  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryAgent", 55) << "reply with discovery beacon" << IBRCOMMON_LOGGER_ENDL;
235 
236  // reply with an own announcement
237  onAdvertise();
238 
239  // remember timestamp of last sent discovery
240  _last_announce_sent = ts;
241  }
242  }
243  }
244 
245  void DiscoveryAgent::onAdvertise()
246  {
247  // check if announcements are enabled
248  if (!_enabled) return;
249 
250  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryAgent", 55) << "advertise discovery beacon" << IBRCOMMON_LOGGER_ENDL;
251 
253 
254  switch (_config.version())
255  {
256  case 2:
258  break;
259 
260  case 1:
262  break;
263 
264  case 0:
265  IBRCOMMON_LOGGER_TAG("DiscoveryAgent", info) << "DTN2 compatibility mode" << IBRCOMMON_LOGGER_ENDL;
267  break;
268  };
269 
271 
272  // set sequencenumber
273  beacon.setSequencenumber(_sn);
274 
275  ibrcommon::MutexLock l(_provider_lock);
276 
277  // get list for ANY interface
278  const handler_list &any_list = _providers[_any_iface];
279 
280  for (handler_map::const_iterator it_p = _providers.begin(); it_p != _providers.end(); ++it_p)
281  {
282  const ibrcommon::vinterface &iface = (*it_p).first;
283  const handler_list &plist = (*it_p).second;
284 
285  // clear all services
286  beacon.clearServices();
287 
288  // collect services from providers
289  if (!_config.shortbeacon())
290  {
291  for (handler_list::const_iterator iter = plist.begin(); iter != plist.end(); ++iter)
292  {
293  DiscoveryBeaconHandler &handler = (**iter);
294 
295  try {
296  // update service information
297  handler.onUpdateBeacon(iface, beacon);
299 
300  }
301  }
302 
303  // add service information for ANY interface
304  if (iface != _any_iface)
305  {
306  for (handler_list::const_iterator iter = any_list.begin(); iter != any_list.end(); ++iter)
307  {
308  DiscoveryBeaconHandler &handler = (**iter);
309 
310  try {
311  // update service information
312  handler.onUpdateBeacon(iface, beacon);
314 
315  }
316  }
317  }
318  }
319 
320  // broadcast announcement
321  for (handler_list::const_iterator iter = plist.begin(); iter != plist.end(); ++iter)
322  {
323  DiscoveryBeaconHandler &handler = (**iter);
324 
325  // broadcast beacon
326  handler.onAdvertiseBeacon(iface, beacon);
327  }
328  }
329 
330  // save the time of the last sent announcement
331  _last_announce_sent = dtn::utils::Clock::getTime();
332 
333  // increment sequencenumber
334  _sn++;
335  }
336  }
337 }