void IPNDAgent::join(const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) throw () { IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "Join on " << iface.toString() << " (" << addr.toString() << ", family: " << addr.family() << ")" << IBRCOMMON_LOGGER_ENDL; // only join IPv6 and IPv4 addresses if ((addr.family() != AF_INET) && (addr.family() != AF_INET6)) return; // do not join on loopback interfaces if (addr.isLocal()) return; // create a multicast socket and bind to given addr ibrcommon::multicastsocket *msock = new ibrcommon::multicastsocket(addr); // if we are in UP state if (_state) { try { // bring up msock->up(); // listen to multicast addresses for (std::set<ibrcommon::vaddress>::const_iterator it_addr = _destinations.begin(); it_addr != _destinations.end(); ++it_addr) { if (msock->get_family() != it_addr->family()) continue; try { msock->join(*it_addr, iface); } catch (const ibrcommon::socket_raw_error &e) { if (e.error() == EADDRINUSE) { // silent error } else if (e.error() == 92) { // silent error - protocol not available } else { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) << "Join to " << (*it_addr).toString() << " failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } catch (const ibrcommon::socket_exception &e) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "Join to " << (*it_addr).toString() << " failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } } catch (const ibrcommon::socket_exception &ex) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) << "Join failed on " << iface.toString() << " (" << addr.toString() << ", family: " << addr.family() << ")" << "; " << ex.what() << IBRCOMMON_LOGGER_ENDL; delete msock; return; } } // add multicast socket to _socket _socket.add(msock, iface); }
void IPNDAgent::leave(const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) throw () { IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "Leave " << iface.toString() << " (" << addr.toString() << ", family: " << addr.family() << ")" << IBRCOMMON_LOGGER_ENDL; // get all sockets bound to the given interface ibrcommon::socketset ifsocks = _socket.get(iface); for (ibrcommon::socketset::iterator it = ifsocks.begin(); it != ifsocks.end(); ++it) { ibrcommon::multicastsocket *msock = dynamic_cast<ibrcommon::multicastsocket*>(*it); if (msock == NULL) continue; if (msock->get_address() == addr) { // remove the socket _socket.remove(msock); // shutdown the socket try { msock->down(); } catch (const ibrcommon::socket_exception &ex) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "leave failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL; } // delete the socket delete msock; return; } } }
void IPNDAgent::join_interface(const ibrcommon::vinterface &iface) throw () { ibrcommon::multicastsocket &msock = dynamic_cast<ibrcommon::multicastsocket&>(**_recv_socket.getAll().begin()); for (std::set<ibrcommon::vaddress>::const_iterator it_addr = _destinations.begin(); it_addr != _destinations.end(); ++it_addr) { try { msock.join(*it_addr, iface); } catch (const ibrcommon::socket_raw_error &e) { if (e.error() != EADDRINUSE) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) << "join failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } catch (const ibrcommon::socket_exception &e) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "can not join " << (*it_addr).toString() << " on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } }
void IPNDAgent::join(const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) throw () { // only join IPv6 and IPv4 addresses if ((addr.family() != AF_INET) && (addr.family() != AF_INET6)) return; // do not join on loopback interfaces if (addr.isLocal()) return; // create a multicast socket and bind to given addr ibrcommon::multicastsocket *msock = new ibrcommon::multicastsocket(addr); try { // bring up msock->up(); // add multicast socket to _socket _socket.add(msock, iface); } catch (const ibrcommon::socket_exception &ex) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) << "Can not send on " << iface.toString() << " (" << addr.toString() << ", family: " << addr.family() << ")" << "; " << ex.what() << IBRCOMMON_LOGGER_ENDL; delete msock; } }
void IPNDAgent::onAdvertiseBeacon(const ibrcommon::vinterface &iface, const DiscoveryBeacon &beacon) throw () { // serialize announcement stringstream ss; ss << beacon; const std::string data = ss.str(); // get all sockets for the given interface ibrcommon::socketset fds = _socket.get(iface); // send out discovery announcements on all bound sockets // (hopefully only one per interface) for (ibrcommon::socketset::const_iterator iter = fds.begin(); iter != fds.end(); ++iter) { try { ibrcommon::udpsocket &sock = dynamic_cast<ibrcommon::udpsocket&>(**iter); // send beacon to all addresses for (std::set<ibrcommon::vaddress>::const_iterator addr_it = _destinations.begin(); addr_it != _destinations.end(); ++addr_it) { const ibrcommon::vaddress &addr = (*addr_it); try { // prevent broadcasting in the wrong address family if (addr.family() != sock.get_family()) continue; sock.sendto(data.c_str(), data.length(), 0, addr); } catch (const ibrcommon::socket_exception &e) { 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; } catch (const ibrcommon::vaddress::address_exception &ex) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) << ex.what() << IBRCOMMON_LOGGER_ENDL; } } } catch (const std::bad_cast&) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, error) << "Socket for sending isn't a udpsocket." << IBRCOMMON_LOGGER_ENDL; } } }
void IPNDAgent::send(const DiscoveryAnnouncement &a, const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr) { // serialize announcement stringstream ss; ss << a; const std::string data = ss.str(); ibrcommon::socketset fds = _send_socket.get(iface); // send out discovery announcements on all bound sockets // (hopefully only one per interface) for (ibrcommon::socketset::const_iterator iter = fds.begin(); iter != fds.end(); ++iter) { ibrcommon::udpsocket &sock = dynamic_cast<ibrcommon::udpsocket&>(**iter); try { // prevent broadcasting in the wrong address family if (addr.family() != sock.get_family()) continue; sock.sendto(data.c_str(), data.length(), 0, addr); } catch (const ibrcommon::socket_exception &e) { 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; } catch (const ibrcommon::vaddress::address_exception &ex) { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) << ex.what() << IBRCOMMON_LOGGER_ENDL; } } }
void IPNDAgent::join(const ibrcommon::vinterface &iface) throw () { // register as discovery handler for this interface dtn::core::BundleCore::getInstance().getDiscoveryAgent().registerService(iface, this); // do not create sockets for any interface if (!iface.isAny()) { // subscribe to NetLink events on our interfaces ibrcommon::LinkManager::getInstance().addEventListener(iface, this); /** * create sockets for each address on the interface */ const std::list<ibrcommon::vaddress> addrs = iface.getAddresses(); for (std::list<ibrcommon::vaddress>::const_iterator it = addrs.begin(); it != addrs.end(); ++it) { const ibrcommon::vaddress addr = (*it); // join to all multicast addresses on this interface join(iface, addr); } } /** * subscribe to multicast address on this interface using the sockets bound to any address */ const ibrcommon::vinterface any_iface(ibrcommon::vinterface::ANY); ibrcommon::socketset anysocks = _socket.get(any_iface); for (ibrcommon::socketset::iterator it = anysocks.begin(); it != anysocks.end(); ++it) { ibrcommon::multicastsocket *msock = dynamic_cast<ibrcommon::multicastsocket*>(*it); if (msock == NULL) continue; for (std::set<ibrcommon::vaddress>::const_iterator addr_it = _destinations.begin(); addr_it != _destinations.end(); ++addr_it) { const ibrcommon::vaddress &addr = (*addr_it); // join only if family matches if (addr.family() != msock->get_family()) continue; try { msock->join(addr, iface); IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "Joined " << addr.toString() << " on " << iface.toString() << IBRCOMMON_LOGGER_ENDL; } catch (const ibrcommon::socket_raw_error &e) { if (e.error() == EADDRINUSE) { // silent error } else if (e.error() == 92) { // silent error - protocol not available } else { IBRCOMMON_LOGGER_TAG(IPNDAgent::TAG, warning) << "Join to " << addr.toString() << " failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } catch (const ibrcommon::socket_exception &e) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "Join to " << addr.toString() << " failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } } }
void IPNDAgent::leave(const ibrcommon::vinterface &iface) throw () { // subscribe to NetLink events on our interfaces ibrcommon::LinkManager::getInstance().removeEventListener(iface, this); // un-register as discovery handler for this interface dtn::core::BundleCore::getInstance().getDiscoveryAgent().unregisterService(iface, this); // get all sockets bound to any interface ibrcommon::socketset anysocks = _socket.get(ibrcommon::vinterface(ibrcommon::vinterface::ANY)); for (ibrcommon::socketset::iterator it = anysocks.begin(); it != anysocks.end(); ++it) { ibrcommon::multicastsocket *msock = dynamic_cast<ibrcommon::multicastsocket*>(*it); if (msock == NULL) continue; for (std::set<ibrcommon::vaddress>::const_iterator addr_it = _destinations.begin(); addr_it != _destinations.end(); ++addr_it) { const ibrcommon::vaddress &addr = (*addr_it); // leave only if family matches if (addr.family() != msock->get_family()) continue; try { msock->leave(addr, iface); } catch (const ibrcommon::socket_exception &e) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "Leave of " << addr.toString() << " failed on " << iface.toString() << "; " << e.what() << IBRCOMMON_LOGGER_ENDL; } } } // get all sockets bound to the given interface ibrcommon::socketset ifsocks = _socket.get(iface); for (ibrcommon::socketset::iterator it = ifsocks.begin(); it != ifsocks.end(); ++it) { ibrcommon::multicastsocket *msock = dynamic_cast<ibrcommon::multicastsocket*>(*it); if (msock == NULL) continue; // remove the socket _socket.remove(msock); // shutdown the socket try { msock->down(); } catch (const ibrcommon::socket_exception &ex) { IBRCOMMON_LOGGER_DEBUG_TAG(IPNDAgent::TAG, 10) << "Socket down failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL; } // delete the socket delete msock; } }