IBR-DTNSuite  0.12
LinkMonitor.cpp
Go to the documentation of this file.
1 /*
2  * LinkMonitor.cpp
3  *
4  * Copyright (C) 2013 IBR, TU Braunschweig
5  *
6  * Written-by: David Goltzsche <goltzsch@ibr.cs.tu-bs.de>
7  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Created on: Sep 9, 2013
22  */
23 
26 #include "ibrcommon/Logger.h"
27 
28 #include <algorithm>
29 
30 namespace ibrcommon
31 {
32  const std::string LinkMonitor::TAG = "LinkMonitor";
33 
35  : _lmgr(lm), _running(true)
36  {
37  }
38 
40  {
41  // wait until the run-loop is finished
42  join();
43  }
44 
45  void LinkMonitor::add(const ibrcommon::vinterface &iface) throw ()
46  {
47  // check if there exists an address set for this interface
48  if (_addr_map.find(iface) != _addr_map.end()) return;
49 
50  // get all addresses on this interface
51  std::list<vaddress> addr = _lmgr.getAddressList(iface);
52 
53  // add all addresses of the interface to the known addresses list
54  _addr_map[iface].insert(addr.begin(), addr.end());
55  }
56 
57  void LinkMonitor::remove() throw ()
58  {
59  // get all monitored interfaces
60  const std::set<vinterface> ifaces = _lmgr.getMonitoredInterfaces();
61 
62  // remove no longer monitored interfaces
63  for (iface_map::iterator it = _addr_map.begin(); it != _addr_map.end();) {
64  const ibrcommon::vinterface &iface = (*it).first;
65 
66  if (ifaces.find(iface) == ifaces.end()) {
67  // remove the entry
68  _addr_map.erase(it++);
69  } else {
70  ++it;
71  }
72  }
73  }
74 
75  void LinkMonitor::run() throw ()
76  {
77  ibrcommon::MutexLock l(_cond);
78 
79  while(_running)
80  {
81  // get all monitored interfaces
82  const std::set<vinterface> ifaces = _lmgr.getMonitoredInterfaces();
83 
84  // check each interface for changed addresses
85  for(std::set<vinterface>::const_iterator iface_iter = ifaces.begin(); iface_iter != ifaces.end(); iface_iter++)
86  {
87  const ibrcommon::vinterface &iface = (*iface_iter);
88 
89  // get current addresses from LinkManager
90  std::list<vaddress> addr_new = _lmgr.getAddressList(iface);
91 
92  // sort all new addresses
93  addr_new.sort();
94 
95  // check if there exists an address set for this interface
96  if (_addr_map.find(iface) == _addr_map.end()) {
97  // create a new address set
98  _addr_map[iface] = addr_set();
99  }
100 
101  // get the address set of last known addresses
102  addr_set &addr_old = _addr_map[iface];
103 
104  // create a set for address differences
105  std::list<vaddress> addr_diff;
106 
107  // find deleted addresses by difference between old and new addresses
108  std::set_difference(addr_old.begin(), addr_old.end(), addr_new.begin(), addr_new.end(), std::back_inserter(addr_diff));
109 
110  // announce each removed address with a LinkEvent
111  for(std::list<vaddress>::const_iterator addr_iter = addr_diff.begin(); addr_iter != addr_diff.end(); addr_iter++)
112  {
113  const ibrcommon::vaddress &addr = (*addr_iter);
114 
115  // remove deleted address from map
116  addr_old.erase(addr);
117 
118  // debug
119  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 60) << "address " << addr.address() << " removed from interface " << iface.toString() << IBRCOMMON_LOGGER_ENDL;
120 
121  // raise event
123  _lmgr.raiseEvent(lme);
124  }
125 
126  // clear the result set
127  addr_diff.clear();
128 
129  // find added addresses by difference between new and old addresses
130  std::set_difference(addr_new.begin(), addr_new.end(), addr_old.begin(), addr_old.end(), std::back_inserter(addr_diff));
131 
132  // announce each added address with a LinkEvent
133  for(std::list<vaddress>::const_iterator addr_iter = addr_diff.begin(); addr_iter != addr_diff.end(); addr_iter++)
134  {
135  const ibrcommon::vaddress &addr = (*addr_iter);
136 
137  // add new address to map
138  addr_old.insert(addr);
139 
140  // debug
141  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 60) << "address " << addr.address() << " added to interface " << iface.toString() << IBRCOMMON_LOGGER_ENDL;
142 
143  // raise event
144  LinkEvent lme(LinkEvent::ACTION_ADDRESS_ADDED, iface, addr);
145  _lmgr.raiseEvent(lme);
146  }
147  }
148 
149  // take breath
150  yield();
151 
152  try {
153  // wait until the next check
154  _cond.wait(_lmgr.getLinkRequestInterval());
155  } catch (const Conditional::ConditionalAbortException &e){
156  // reached, if conditional timed out
158 
159  // exit on abort
160  return;
161  }
162  }
163  }
164 
166  {
167  // debug
168  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 60) << "cancelled" << IBRCOMMON_LOGGER_ENDL;
169 
170  // shutdown the run-loop
171  ibrcommon::MutexLock l(_cond);
172  _running = false;
173  _cond.signal(true);
174  }
175 }
176