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::componentUp()
00133 {
00134 DiscoveryAgent::componentUp();
00135
00136
00137 for (std::list<ibrcommon::vinterface>::const_iterator iter = _interfaces.begin(); iter != _interfaces.end(); iter++)
00138 {
00139 const ibrcommon::vinterface &iface = *iter;
00140 if (!iface.empty())
00141 {
00142 _socket.bind(iface, 0, SOCK_DGRAM);
00143 }
00144 }
00145
00146
00147 if (_destination.isMulticast())
00148 {
00149
00150 _socket.bind(_destination, _port, SOCK_DGRAM);
00151
00152 for (std::list<ibrcommon::vinterface>::const_iterator i_iter = _interfaces.begin(); i_iter != _interfaces.end(); i_iter++)
00153 {
00154 const ibrcommon::vinterface &iface = *i_iter;
00155
00156
00157 std::list<int> fds = _socket.get(iface, ibrcommon::vaddress::VADDRESS_INET);
00158
00159
00160 for (std::list<int>::const_iterator iter = fds.begin();
00161 iter != fds.end(); iter++)
00162 {
00163
00164 ibrcommon::MulticastSocket ms(*iter);
00165 ms.joinGroup(_destination, iface);
00166 }
00167 }
00168 }
00169 else
00170 {
00171
00172 _socket.bind(_destination, _port, SOCK_DGRAM);
00173 }
00174 }
00175
00176 void IPNDAgent::componentDown()
00177 {
00178 _socket.shutdown();
00179 DiscoveryAgent::componentDown();
00180 }
00181
00182 void IPNDAgent::componentRun()
00183 {
00184 while (true)
00185 {
00186 std::list<int> fds;
00187
00188
00189 ibrcommon::select(_socket, fds, NULL);
00190
00191
00192 for (std::list<int>::const_iterator iter = fds.begin(); iter != fds.end(); iter++)
00193 {
00194 char data[1500];
00195 std::string sender;
00196 DiscoveryAnnouncement announce(_version);
00197
00198 int len = ibrcommon::recvfrom(*iter, data, 1500, sender);
00199
00200 if (announce.isShort())
00201 {
00202
00203 }
00204
00205 if (announce.getServices().empty())
00206 {
00207 announce.addService(dtn::net::DiscoveryService("tcpcl", "ip=" + sender + ";port=4556;"));
00208 }
00209
00210 if (len < 0) return;
00211
00212 stringstream ss;
00213 ss.write(data, len);
00214
00215 try {
00216 ss >> announce;
00217 received(announce);
00218 } catch (const dtn::InvalidDataException&) {
00219 } catch (const ibrcommon::IOException&) {
00220 }
00221
00222 yield();
00223 }
00224 }
00225 }
00226
00227 bool IPNDAgent::__cancellation()
00228 {
00229
00230 ibrcommon::interrupt(_socket, *this);
00231
00232
00233 return true;
00234 }
00235
00236 const std::string IPNDAgent::getName() const
00237 {
00238 return "IPNDAgent";
00239 }
00240 }
00241 }