• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

daemon/src/net/IPNDAgent.cpp

Go to the documentation of this file.
00001 /*
00002  * IPNDAgent.cpp
00003  *
00004  *  Created on: 14.09.2009
00005  *      Author: morgenro
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                         // broadcast addresses should be usable more than once.
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                         // serialize announcement
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                         // set sequencenumber
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                                 // clear all services
00107                                 announcement.clearServices();
00108 
00109                                 if (!_config.shortbeacon())
00110                                 {
00111                                         // add services
00112                                         for (std::list<DiscoveryService>::iterator iter = services.begin(); iter != services.end(); iter++)
00113                                         {
00114                                                 DiscoveryService &service = (*iter);
00115 
00116                                                 try {
00117                                                         // update service information
00118                                                         service.update(iface);
00119 
00120                                                         // add service to discovery message
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                         // create one socket for each interface
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                         // only if the destination is a multicast address
00147                         if (_destination.isMulticast())
00148                         {
00149                                 // bind on the multicast address
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                                         // get all FD of IPv4 sockets matching this interface
00157                                         std::list<int> fds = _socket.get(iface, ibrcommon::vaddress::VADDRESS_INET);
00158 
00159                                         // iterate through all socket FD
00160                                         for (std::list<int>::const_iterator iter = fds.begin();
00161                                                         iter != fds.end(); iter++)
00162                                         {
00163                                                 // enable multicasting on the socket
00164                                                 ibrcommon::MulticastSocket ms(*iter);
00165                                                 ms.joinGroup(_destination, iface);
00166                                         }
00167                                 }
00168                         }
00169                         else
00170                         {
00171                                 // bind on ALL interfaces
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                                 // select on all bound sockets
00189                                 ibrcommon::select(_socket, fds, NULL);
00190 
00191                                 // receive from all sockets
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                                                 // TODO: generate name with the sender address
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                         // interrupt the receiving thread
00230                         ibrcommon::interrupt(_socket, *this);
00231 
00232                         // do not cancel the hard-way
00233                         return true;
00234                 }
00235 
00236                 const std::string IPNDAgent::getName() const
00237                 {
00238                         return "IPNDAgent";
00239                 }
00240         }
00241 }

Generated on Thu Mar 10 2011 15:44:03 for IBR-DTNSuite by  doxygen 1.7.1