IBR-DTN  1.0.0
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/NodeEvent.h"
28 #include "core/EventDispatcher.h"
29 #include <ibrdtn/utils/Utils.h>
30 #include <ibrdtn/utils/Clock.h>
31 #include <ibrcommon/Logger.h>
32 
33 using namespace dtn::core;
34 
35 namespace dtn
36 {
37  namespace net
38  {
39  DiscoveryAgent::DiscoveryAgent()
40  : _config(dtn::daemon::Configuration::getInstance().getDiscovery()),
41  _enabled(true), _sn(0), _adv_next(0), _beacon_period(_config.interval())
42  {
43  }
44 
46  {
47  }
48 
49  const std::string DiscoveryAgent::getName() const
50  {
51  return "DiscoveryAgent";
52  }
53 
55  {
57 
58  if (_config.announce() && (_adv_next <= ts)) {
59  // advertise me
60  onAdvertise();
61 
62  // set next advertisement period
63  _adv_next = ts + _beacon_period;
64  }
65  }
66 
68  {
69  if (global.getAction() == dtn::core::GlobalEvent::GLOBAL_START_DISCOVERY) {
70  // start sending discovery beacons
71  _enabled = true;
72  }
73  else if (global.getAction() == dtn::core::GlobalEvent::GLOBAL_STOP_DISCOVERY) {
74  // suspend discovery beacons
75  _enabled = false;
76  }
77  else if (global.getAction() == dtn::core::GlobalEvent::GLOBAL_LOW_ENERGY) {
78  // suspend mode - pro-long beaconing interval
79  _beacon_period = _config.interval() * 10;
80  }
81  else if (global.getAction() == dtn::core::GlobalEvent::GLOBAL_NORMAL) {
82  // suspend mode stopped - reset beaconing interval
83  _beacon_period = _config.interval();
84  _adv_next = 0;
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 
106  void DiscoveryAgent::registerService(const ibrcommon::vinterface &iface, dtn::net::DiscoveryBeaconHandler *handler)
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 
143  void DiscoveryAgent::unregisterService(const ibrcommon::vinterface &iface, const dtn::net::DiscoveryBeaconHandler *handler)
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  default:
171  break;
172 
173  case 0:
174  IBRCOMMON_LOGGER_TAG("DiscoveryAgent", info) << "DTN2 compatibility mode" << IBRCOMMON_LOGGER_ENDL;
176  break;
177  };
178 
180 
181  // set beaconing period
182  beacon.setPeriod(_beacon_period);
183 
184  return beacon;
185  }
186 
188  {
189  // ignore own beacons
190  if (beacon.getEID() == dtn::core::BundleCore::local) return;
191 
192  // convert the announcement into NodeEvents
193  Node n(beacon.getEID());
194 
195  // if beaconing period is defined by beacon, set time-out to twice the period
196  const dtn::data::Number to_value = beacon.hasPeriod() ? beacon.getPeriod() * 2 : _config.interval() * 2;
197 
198  const std::list<DiscoveryService> &services = beacon.getServices();
199 
200  for (std::list<DiscoveryService>::const_iterator iter = services.begin(); iter != services.end(); ++iter)
201  {
202  const DiscoveryService &s = (*iter);
203 
204  // get protocol from tag
206 
208  {
209  // Set timeout
210  dtn::data::Number to_value_mailcl = to_value;
212  if(configTime > 0)
213  to_value_mailcl = configTime;
214 
215  n.add(Node::URI(Node::NODE_DISCOVERED, Node::CONN_EMAIL, s.getParameters(), to_value_mailcl, -80));
216  }
218  {
219  n.add(Node::Attribute(Node::NODE_DISCOVERED, s.getName(), s.getParameters(), to_value));
220  }
221  else
222  {
223  n.add(Node::URI(Node::NODE_DISCOVERED, p, s.getParameters(), to_value));
224  }
225  }
226 
227  // announce NodeInfo to ConnectionManager
229 
230  // if continuous announcements are disabled, then reply to this message
231  if (!_config.announce() && _enabled)
232  {
233  // first check if another announcement was sent during the same seconds
235 
236  if (_adv_next <= ts)
237  {
238  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryAgent", 55) << "reply with discovery beacon" << IBRCOMMON_LOGGER_ENDL;
239 
240  // reply with an own announcement
241  onAdvertise();
242 
243  // set next advertisement period
244  _adv_next = ts + _beacon_period;
245  }
246  }
247  }
248 
249  void DiscoveryAgent::onAdvertise()
250  {
251  // check if announcements are enabled
252  if (!_enabled) return;
253 
254  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryAgent", 55) << "advertise discovery beacon" << IBRCOMMON_LOGGER_ENDL;
255 
256  DiscoveryBeacon beacon = obtainBeacon();
257 
258  // set sequencenumber
259  beacon.setSequencenumber(_sn);
260 
261  ibrcommon::MutexLock l(_provider_lock);
262 
263  // get list for ANY interface
264  const handler_list &any_list = _providers[_any_iface];
265 
266  for (handler_map::const_iterator it_p = _providers.begin(); it_p != _providers.end(); ++it_p)
267  {
268  const ibrcommon::vinterface &iface = (*it_p).first;
269  const handler_list &plist = (*it_p).second;
270 
271  // clear all services
272  beacon.clearServices();
273 
274  // collect services from providers
275  if (!_config.shortbeacon())
276  {
277  for (handler_list::const_iterator iter = plist.begin(); iter != plist.end(); ++iter)
278  {
279  DiscoveryBeaconHandler &handler = (**iter);
280 
281  try {
282  // update service information
283  handler.onUpdateBeacon(iface, beacon);
285 
286  }
287  }
288 
289  // add service information for ANY interface
290  if (iface != _any_iface)
291  {
292  for (handler_list::const_iterator iter = any_list.begin(); iter != any_list.end(); ++iter)
293  {
294  DiscoveryBeaconHandler &handler = (**iter);
295 
296  try {
297  // update service information
298  handler.onUpdateBeacon(iface, beacon);
300 
301  }
302  }
303  }
304  }
305 
306  // broadcast announcement
307  for (handler_list::const_iterator iter = plist.begin(); iter != plist.end(); ++iter)
308  {
309  DiscoveryBeaconHandler &handler = (**iter);
310 
311  // broadcast beacon
312  handler.onAdvertiseBeacon(iface, beacon);
313  }
314  }
315 
316  // increment sequencenumber
317  _sn++;
318  }
319  }
320 }
static Configuration & getInstance(bool reset=false)
service_list & getServices()
DiscoveryBeacon obtainBeacon() const
static dtn::data::EID local
Definition: BundleCore.h:79
dtn::core::Node::Protocol getProtocol() const
static void add(EventReceiver< E > *receiver)
const std::string & getName() const
static void remove(const EventReceiver< E > *receiver)
void raiseEvent(const dtn::core::TimeEvent &evt)
dtn::net::ConnectionManager & getConnectionManager()
Definition: BundleCore.cpp:260
const dtn::data::EID & getEID() const
void unregisterService(const ibrcommon::vinterface &iface, const dtn::net::DiscoveryBeaconHandler *handler)
const std::string & getParameters() const
virtual void componentDown()
virtual const std::string getName() const
const dtn::data::Number & getPeriod() const
void setPeriod(const dtn::data::Number &period)
virtual void onAdvertiseBeacon(const ibrcommon::vinterface &iface, const DiscoveryBeacon &beacon)
void onBeaconReceived(const DiscoveryBeacon &beacon)
const Configuration::EMail & getEMail() const
static dtn::data::Timestamp getMonotonicTimestamp()
Definition: Clock.cpp:175
void registerService(const ibrcommon::vinterface &iface, dtn::net::DiscoveryBeaconHandler *handler)
virtual void onUpdateBeacon(const ibrcommon::vinterface &iface, DiscoveryBeacon &beacon)
void updateNeighbor(const dtn::core::Node &n)
static BundleCore & getInstance()
Definition: BundleCore.cpp:82
void setSequencenumber(uint16_t sequence)