32 #include <ibrcommon/Logger.h>
33 #include <ibrcommon/TimeMeasurement.h>
34 #include <ibrcommon/net/socket.h>
35 #include <ibrcommon/net/vaddress.h>
36 #include <ibrcommon/link/LinkManager.h>
39 #define EADDRNOTAVAIL WSAEADDRNOTAVAIL
40 #define EADDRINUSE WSAEADDRINUSE
52 const std::string IPNDAgent::TAG =
"IPNDAgent";
57 _virtual_mcast_iface(
"__virtual_multicast_interface__"),
59 _state(false), _port(port)
69 IBRCOMMON_LOGGER_TAG(
"DiscoveryAgent", info) <<
"listen to " << address.toString() << IBRCOMMON_LOGGER_ENDL;
70 _destinations.insert(address);
75 IBRCOMMON_LOGGER_TAG(
"DiscoveryAgent", info) <<
"add interface " << net.toString() << IBRCOMMON_LOGGER_ENDL;
78 ibrcommon::MutexLock l(_interface_lock);
81 if (_interfaces.find(net) != _interfaces.end())
return;
84 _interfaces.insert(net);
87 void IPNDAgent::join(
const ibrcommon::vinterface &iface,
const ibrcommon::vaddress &addr)
throw ()
89 IBRCOMMON_LOGGER_DEBUG_TAG(
TAG, 10) <<
"Join on " << iface.toString() <<
" (" << addr.toString() <<
", family: " << addr.family() <<
")" << IBRCOMMON_LOGGER_ENDL;
92 if ((addr.family() != AF_INET) && (addr.family() != AF_INET6))
return;
95 if (addr.isLocal())
return;
98 ibrcommon::multicastsocket *msock =
new ibrcommon::multicastsocket(addr);
107 for (std::set<ibrcommon::vaddress>::const_iterator it_addr = _destinations.begin(); it_addr != _destinations.end(); ++it_addr)
110 msock->join(*it_addr, iface);
111 }
catch (
const ibrcommon::socket_raw_error &e) {
112 if (e.error() == EADDRINUSE) {
114 }
else if (e.error() == 92) {
117 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) <<
"Join to " << (*it_addr).toString() <<
" failed on " << iface.toString() <<
"; " << e.what() << IBRCOMMON_LOGGER_ENDL;
119 }
catch (
const ibrcommon::socket_exception &e) {
120 IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) <<
"Join to " << (*it_addr).toString() <<
" failed on " << iface.toString() <<
"; " << e.what() << IBRCOMMON_LOGGER_ENDL;
123 }
catch (
const ibrcommon::socket_exception &ex) {
124 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) <<
"Join failed on " << iface.toString() <<
" (" << addr.toString() <<
", family: " << addr.family() <<
")" <<
"; " << ex.what() << IBRCOMMON_LOGGER_ENDL;
131 _socket.add(msock, iface);
134 void IPNDAgent::leave(
const ibrcommon::vinterface &iface,
const ibrcommon::vaddress &addr)
throw ()
136 IBRCOMMON_LOGGER_DEBUG_TAG(
TAG, 10) <<
"Leave " << iface.toString() <<
" (" << addr.toString() <<
", family: " << addr.family() <<
")" << IBRCOMMON_LOGGER_ENDL;
139 ibrcommon::socketset ifsocks = _socket.get(iface);
141 for (ibrcommon::socketset::iterator it = ifsocks.begin(); it != ifsocks.end(); ++it)
143 ibrcommon::multicastsocket *msock =
dynamic_cast<ibrcommon::multicastsocket*
>(*it);
144 if (msock == NULL)
continue;
146 if (msock->get_address() == addr) {
148 _socket.remove(msock);
153 }
catch (
const ibrcommon::socket_exception &ex) {
154 IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) <<
"leave failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
165 void IPNDAgent::leave(
const ibrcommon::vinterface &iface)
throw ()
168 ibrcommon::socketset ifsocks = _socket.get(iface);
170 for (ibrcommon::socketset::iterator it = ifsocks.begin(); it != ifsocks.end(); ++it)
172 ibrcommon::multicastsocket *msock =
dynamic_cast<ibrcommon::multicastsocket*
>(*it);
173 if (msock == NULL)
continue;
176 _socket.remove(msock);
181 }
catch (
const ibrcommon::socket_exception &ex) {
182 IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) <<
"leave failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
190 void IPNDAgent::join(
const ibrcommon::vinterface &iface)
throw ()
192 std::list<ibrcommon::vaddress> addrs = iface.getAddresses();
194 for (std::list<ibrcommon::vaddress>::const_iterator it = addrs.begin(); it != addrs.end(); ++it)
196 ibrcommon::vaddress addr = (*it);
197 addr.setService(_port);
205 stringstream ss; ss << beacon;
206 const std::string data = ss.str();
209 ibrcommon::socketset fds = _socket.get(iface);
213 for (ibrcommon::socketset::const_iterator iter = fds.begin(); iter != fds.end(); ++iter)
216 ibrcommon::udpsocket &sock =
dynamic_cast<ibrcommon::udpsocket&
>(**iter);
219 for (std::set<ibrcommon::vaddress>::const_iterator addr_it = _destinations.begin(); addr_it != _destinations.end(); ++addr_it)
221 const ibrcommon::vaddress &addr = (*addr_it);
225 if (addr.family() != sock.get_family())
continue;
227 sock.sendto(data.c_str(), data.length(), 0, addr);
228 }
catch (
const ibrcommon::socket_exception &e) {
229 IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 5) <<
"can not send message to " << addr.toString() <<
" via " << sock.get_address().toString() <<
"/" << iface.toString() <<
"; socket exception: " << e.what() << IBRCOMMON_LOGGER_ENDL;
230 }
catch (
const ibrcommon::vaddress::address_exception &ex) {
231 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) << ex.what() << IBRCOMMON_LOGGER_ENDL;
234 }
catch (
const std::bad_cast&) {
235 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) <<
"Socket for sending isn't a udpsocket." << IBRCOMMON_LOGGER_ENDL;
248 ibrcommon::MutexLock l(_interface_lock);
251 if (_interfaces.find(dialup.iface) != _interfaces.end())
break;
254 _interfaces.insert(dialup.iface);
258 ibrcommon::LinkManager::getInstance().addEventListener(dialup.iface,
this);
272 ibrcommon::MutexLock l(_interface_lock);
275 if (_interfaces.find(dialup.iface) == _interfaces.end())
break;
278 _interfaces.erase(dialup.iface);
282 ibrcommon::LinkManager::getInstance().removeEventListener(dialup.iface,
this);
298 ibrcommon::MutexLock l(_interface_lock);
299 if (_interfaces.find(evt.getInterface()) == _interfaces.end())
return;
302 switch (evt.getAction())
304 case ibrcommon::LinkEvent::ACTION_ADDRESS_ADDED:
306 ibrcommon::vaddress addr = evt.getAddress();
307 addr.setService(_port);
308 join(evt.getInterface(), addr);
312 case ibrcommon::LinkEvent::ACTION_ADDRESS_REMOVED:
314 ibrcommon::vaddress addr = evt.getAddress();
315 addr.setService(_port);
316 leave(evt.getInterface(), addr);
320 case ibrcommon::LinkEvent::ACTION_LINK_DOWN:
323 leave(evt.getInterface());
342 }
catch (
const ibrcommon::socket_exception &ex) {
343 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) << ex.what() << IBRCOMMON_LOGGER_ENDL;
347 std::set<sa_family_t> bound_set;
351 for (std::set<ibrcommon::vaddress>::const_iterator it_addr = _destinations.begin(); it_addr != _destinations.end(); ++it_addr)
353 const ibrcommon::vaddress &addr = (*it_addr);
356 sa_family_t fam = addr.family();
358 if (bound_set.find(fam) == bound_set.end()) {
359 const ibrcommon::vaddress any_addr(_port, fam);
362 ibrcommon::multicastsocket *msock =
new ibrcommon::multicastsocket(any_addr);
369 _socket.add(msock, _virtual_mcast_iface);
370 }
catch (
const ibrcommon::socket_exception &ex) {
371 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) <<
"failed to set-up multicast socket on " << any_addr.toString() <<
": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
375 bound_set.insert(fam);
377 }
catch (
const ibrcommon::vaddress::address_exception &ex) {
378 IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) <<
"unsupported multicast address " << addr.toString() <<
": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
387 ibrcommon::MutexLock l(_interface_lock);
389 for (std::set<ibrcommon::vinterface>::const_iterator it_iface = _interfaces.begin(); it_iface != _interfaces.end(); ++it_iface)
391 const ibrcommon::vinterface &iface = (*it_iface);
394 ibrcommon::LinkManager::getInstance().addEventListener(iface,
this);
410 ibrcommon::LinkManager::getInstance().removeEventListener(
this);
421 ibrcommon::JoinableThread::stop();
422 ibrcommon::JoinableThread::join();
439 ibrcommon::socketset fds;
443 _socket.select(&fds, NULL, NULL, &tv);
446 for (ibrcommon::socketset::const_iterator iter = fds.begin(); iter != fds.end(); ++iter)
448 ibrcommon::multicastsocket &sock =
dynamic_cast<ibrcommon::multicastsocket&
>(**iter);
451 ibrcommon::vaddress sender;
454 ssize_t len = sock.recvfrom(data, 1500, 0, sender);
464 if (beacon.isShort())
476 for (dtn::net::DiscoveryBeacon::service_list::iterator iter = services.begin(); iter != services.end(); ++iter) {
479 if ( (service.
getParameters().find(
"port=") != std::string::npos) &&
480 (service.
getParameters().find(
"ip=") == std::string::npos) ) {
490 }
catch (
const ibrcommon::IOException&) {
495 if ( tv.tv_sec <= 0 && tv.tv_usec <= 0 )
496 throw ibrcommon::vsocket_timeout(
"timeout");
498 }
catch (
const ibrcommon::vsocket_timeout&) {
506 }
catch (
const ibrcommon::vsocket_interrupt&) {
508 }
catch (
const ibrcommon::socket_exception &ex) {
510 IBRCOMMON_LOGGER_TAG(
IPNDAgent::TAG, error) <<
"unexpected error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
std::list< DiscoveryService > service_list
DiscoveryBeacon obtainBeacon() const
static void add(EventReceiver< E > *receiver)
void setEID(const dtn::data::EID &eid)
void update(const std::string ¶meters)
void add(const ibrcommon::vaddress &address)
virtual const std::string getName() const
static void remove(const EventReceiver< E > *receiver)
void raiseEvent(const dtn::net::P2PDialupEvent &evt)
dtn::net::DiscoveryAgent & getDiscoveryAgent()
virtual void componentRun()
void unregisterService(const ibrcommon::vinterface &iface, const dtn::net::DiscoveryBeaconHandler *handler)
const std::string & getParameters() const
void eventNotify(const ibrcommon::LinkEvent &evt)
virtual void componentUp()
void onBeaconReceived(const DiscoveryBeacon &beacon)
void registerService(const ibrcommon::vinterface &iface, dtn::net::DiscoveryBeaconHandler *handler)
virtual void componentDown()
void bind(const ibrcommon::vinterface &net)
static BundleCore & getInstance()
void onAdvertiseBeacon(const ibrcommon::vinterface &iface, const DiscoveryBeacon &beacon)