Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include "net/IPNDAgent.h"
00009 #include "core/BundleCore.h"
00010 #include <ibrdtn/data/Exceptions.h>
00011 #include <sstream>
00012 #include <string.h>
00013 #include <ibrcommon/Logger.h>
00014 #include <ibrcommon/net/MulticastSocket.h>
00015 #include "Configuration.h"
00016 #include <typeinfo>
00017
00018 namespace dtn
00019 {
00020 namespace net
00021 {
00022 IPNDAgent::IPNDAgent(int port, const ibrcommon::vaddress &address)
00023 : DiscoveryAgent(dtn::daemon::Configuration::getInstance().getDiscovery()),
00024 _version(DiscoveryAnnouncement::DISCO_VERSION_01), _destination(address), _port(port)
00025 {
00026
00027 _socket.set(ibrcommon::vsocket::VSOCKET_REUSEADDR);
00028
00029 if (_destination.isMulticast())
00030 {
00031 IBRCOMMON_LOGGER(info) << "DiscoveryAgent: multicast mode " << address.toString() << ":" << port << IBRCOMMON_LOGGER_ENDL;
00032 _socket.set(ibrcommon::vsocket::VSOCKET_MULTICAST);
00033 }
00034 else
00035 {
00036 IBRCOMMON_LOGGER(info) << "DiscoveryAgent: broadcast mode " << address.toString() << ":" << port << IBRCOMMON_LOGGER_ENDL;
00037 _socket.set(ibrcommon::vsocket::VSOCKET_BROADCAST);
00038 }
00039
00040 switch (_config.version())
00041 {
00042 case 2:
00043 _version = DiscoveryAnnouncement::DISCO_VERSION_01;
00044 break;
00045
00046 case 1:
00047 _version = DiscoveryAnnouncement::DISCO_VERSION_00;
00048 break;
00049
00050 case 0:
00051 IBRCOMMON_LOGGER(info) << "DiscoveryAgent: DTN2 compatibility mode" << IBRCOMMON_LOGGER_ENDL;
00052 _version = DiscoveryAnnouncement::DTND_IPDISCOVERY;
00053 break;
00054 };
00055 }
00056
00057 IPNDAgent::~IPNDAgent()
00058 {
00059 }
00060
00061 void IPNDAgent::bind(const ibrcommon::vinterface &net)
00062 {
00063 IBRCOMMON_LOGGER(info) << "DiscoveryAgent: bind to interface " << net.toString() << IBRCOMMON_LOGGER_ENDL;
00064 _interfaces.push_back(net);
00065 }
00066
00067 void IPNDAgent::send(const DiscoveryAnnouncement &a, const ibrcommon::vinterface &iface, const ibrcommon::vaddress &addr, const unsigned int port)
00068 {
00069
00070 stringstream ss; ss << a;
00071 const std::string data = ss.str();
00072
00073 std::list<int> fds = _socket.get(iface);
00074 for (std::list<int>::const_iterator iter = fds.begin(); iter != fds.end(); iter++)
00075 {
00076 try {
00077 size_t ret = 0;
00078 int flags = 0;
00079
00080 struct addrinfo hints, *ainfo;
00081 memset(&hints, 0, sizeof hints);
00082
00083 hints.ai_socktype = SOCK_DGRAM;
00084 ainfo = addr.addrinfo(&hints, port);
00085
00086 ret = sendto(*iter, data.c_str(), data.length(), flags, ainfo->ai_addr, ainfo->ai_addrlen);
00087
00088 freeaddrinfo(ainfo);
00089 } catch (const ibrcommon::vsocket_exception&) {
00090 IBRCOMMON_LOGGER_DEBUG(5) << "can not send message to " << addr.toString() << IBRCOMMON_LOGGER_ENDL;
00091 }
00092 }
00093 }
00094
00095 void IPNDAgent::sendAnnoucement(const u_int16_t &sn, std::list<DiscoveryService> &services)
00096 {
00097 DiscoveryAnnouncement announcement(_version, dtn::core::BundleCore::local);
00098
00099
00100 announcement.setSequencenumber(sn);
00101
00102 for (std::list<ibrcommon::vinterface>::const_iterator it_iface = _interfaces.begin(); it_iface != _interfaces.end(); it_iface++)
00103 {
00104 const ibrcommon::vinterface &iface = (*it_iface);
00105
00106
00107 announcement.clearServices();
00108
00109 if (!_config.shortbeacon())
00110 {
00111
00112 for (std::list<DiscoveryService>::iterator iter = services.begin(); iter != services.end(); iter++)
00113 {
00114 DiscoveryService &service = (*iter);
00115
00116 try {
00117
00118 service.update(iface);
00119
00120
00121 announcement.addService(service);
00122 } catch (const dtn::net::DiscoveryServiceProvider::NoServiceHereException&) {
00123
00124 }
00125 }
00126 }
00127
00128 send(announcement, iface, _destination, _port);
00129 }
00130 }
00131
00132 void IPNDAgent::eventNotify(const ibrcommon::LinkManagerEvent &evt)
00133 {
00134 if (evt.getType() == ibrcommon::LinkManagerEvent::EVENT_ADDRESS_ADDED)
00135 {
00136 if (_destination.isMulticast())
00137 {
00138 __join_multicast_groups__(evt.getInterface());
00139 }
00140 }
00141 }
00142
00143 void IPNDAgent::__join_multicast_groups__(const ibrcommon::vinterface &iface)
00144 {
00145
00146 std::list<int> fds = _socket.get(iface, ibrcommon::vaddress::VADDRESS_INET);
00147
00148
00149 for (std::list<int>::const_iterator iter = fds.begin();
00150 iter != fds.end(); iter++)
00151 {
00152
00153 ibrcommon::MulticastSocket ms(*iter);
00154 ms.joinGroup(_destination, iface);
00155 }
00156 }
00157
00158 void IPNDAgent::componentUp()
00159 {
00160 DiscoveryAgent::componentUp();
00161
00162
00163 for (std::list<ibrcommon::vinterface>::const_iterator iter = _interfaces.begin(); iter != _interfaces.end(); iter++)
00164 {
00165 const ibrcommon::vinterface &iface = *iter;
00166 if (!iface.empty())
00167 {
00168 _socket.bind(iface, 0, SOCK_DGRAM);
00169 }
00170 }
00171
00172
00173 if (_destination.isMulticast())
00174 {
00175
00176 _socket.bind(_destination, _port, SOCK_DGRAM);
00177
00178 for (std::list<ibrcommon::vinterface>::const_iterator i_iter = _interfaces.begin(); i_iter != _interfaces.end(); i_iter++)
00179 {
00180
00181 __join_multicast_groups__(*i_iter);
00182 }
00183 }
00184 else
00185 {
00186
00187 _socket.bind(_destination, _port, SOCK_DGRAM);
00188 }
00189
00190
00191 _socket.setEventCallback(this);
00192 }
00193
00194 void IPNDAgent::componentDown()
00195 {
00196
00197 _socket.setEventCallback(NULL);
00198
00199
00200 _socket.shutdown();
00201 DiscoveryAgent::componentDown();
00202 }
00203
00204 void IPNDAgent::componentRun()
00205 {
00206 while (true)
00207 {
00208 std::list<int> fds;
00209
00210
00211 ibrcommon::select(_socket, fds, NULL);
00212
00213
00214 for (std::list<int>::const_iterator iter = fds.begin(); iter != fds.end(); iter++)
00215 {
00216 char data[1500];
00217 std::string sender;
00218 DiscoveryAnnouncement announce(_version);
00219
00220 int len = ibrcommon::recvfrom(*iter, data, 1500, sender);
00221
00222 if (announce.isShort())
00223 {
00224
00225 }
00226
00227 if (announce.getServices().empty())
00228 {
00229 announce.addService(dtn::net::DiscoveryService("tcpcl", "ip=" + sender + ";port=4556;"));
00230 }
00231
00232 if (len < 0) return;
00233
00234 stringstream ss;
00235 ss.write(data, len);
00236
00237 try {
00238 ss >> announce;
00239 received(announce);
00240 } catch (const dtn::InvalidDataException&) {
00241 } catch (const ibrcommon::IOException&) {
00242 }
00243
00244 yield();
00245 }
00246 }
00247 }
00248
00249 bool IPNDAgent::__cancellation()
00250 {
00251
00252 ibrcommon::interrupt(_socket, *this);
00253
00254
00255 return true;
00256 }
00257
00258 const std::string IPNDAgent::getName() const
00259 {
00260 return "IPNDAgent";
00261 }
00262 }
00263 }