• 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::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                         // get all FD of IPv4 sockets matching this interface
00146                         std::list<int> fds = _socket.get(iface, ibrcommon::vaddress::VADDRESS_INET);
00147 
00148                         // iterate through all socket FD
00149                         for (std::list<int>::const_iterator iter = fds.begin();
00150                                         iter != fds.end(); iter++)
00151                         {
00152                                 // enable multicasting on the socket
00153                                 ibrcommon::MulticastSocket ms(*iter);
00154                                 ms.joinGroup(_destination, iface);
00155                         }
00156                 }
00157 
00158                 void IPNDAgent::componentUp()
00159                 {
00160                         DiscoveryAgent::componentUp();
00161 
00162                         // create one socket for each interface
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                         // only if the destination is a multicast address
00173                         if (_destination.isMulticast())
00174                         {
00175                                 // bind on the multicast address
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                                         // enable multicast
00181                                         __join_multicast_groups__(*i_iter);
00182                                 }
00183                         }
00184                         else
00185                         {
00186                                 // bind on ALL interfaces
00187                                 _socket.bind(_destination, _port, SOCK_DGRAM);
00188                         }
00189 
00190                         // set this socket as listener to socket events
00191                         _socket.setEventCallback(this);
00192                 }
00193 
00194                 void IPNDAgent::componentDown()
00195                 {
00196                         // unset this socket as listener to socket events
00197                         _socket.setEventCallback(NULL);
00198 
00199                         // shutdown the sockets
00200                         _socket.shutdown();
00201                         DiscoveryAgent::componentDown();
00202                 }
00203 
00204                 void IPNDAgent::componentRun()
00205                 {
00206                         while (true)
00207                         {
00208                                 std::list<int> fds;
00209 
00210                                 // select on all bound sockets
00211                                 ibrcommon::select(_socket, fds, NULL);
00212 
00213                                 // receive from all sockets
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                                                 // TODO: generate name with the sender address
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                         // interrupt the receiving thread
00252                         ibrcommon::interrupt(_socket, *this);
00253 
00254                         // do not cancel the hard-way
00255                         return true;
00256                 }
00257 
00258                 const std::string IPNDAgent::getName() const
00259                 {
00260                         return "IPNDAgent";
00261                 }
00262         }
00263 }

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1