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

daemon/src/net/LOWPANConvergenceLayer.cpp

Go to the documentation of this file.
00001 #include "net/LOWPANConvergenceLayer.h"
00002 #include "net/BundleReceivedEvent.h"
00003 #include "core/BundleEvent.h"
00004 #include "net/TransferCompletedEvent.h"
00005 #include "net/TransferAbortedEvent.h"
00006 #include "routing/RequeueBundleEvent.h"
00007 #include <ibrcommon/net/UnicastSocketLowpan.h>
00008 #include "core/BundleCore.h"
00009 
00010 #include <ibrcommon/data/BLOB.h>
00011 #include <ibrcommon/Logger.h>
00012 #include <ibrcommon/thread/MutexLock.h>
00013 
00014 #include <ibrdtn/utils/Utils.h>
00015 #include <ibrdtn/data/Serializer.h>
00016 
00017 #include <sys/socket.h>
00018 #include <poll.h>
00019 #include <errno.h>
00020 
00021 #include <sys/types.h>
00022 #include <netinet/in.h>
00023 #include <arpa/inet.h>
00024 #include <unistd.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <fcntl.h>
00029 #include <limits.h>
00030 
00031 #include <iostream>
00032 
00033 
00034 using namespace dtn::data;
00035 
00036 namespace dtn
00037 {
00038         namespace net
00039         {
00040                 const int LOWPANConvergenceLayer::DEFAULT_PANID = 0x780;
00041 
00042                 LOWPANConvergenceLayer::LOWPANConvergenceLayer(ibrcommon::NetInterface net, int panid, bool, unsigned int mtu)
00043                         : _socket(NULL), _net(net), _panid(panid), m_maxmsgsize(mtu), _running(false)
00044                 {
00045                         _socket = new ibrcommon::UnicastSocketLowpan();
00046                 }
00047 
00048                 LOWPANConvergenceLayer::~LOWPANConvergenceLayer()
00049                 {
00050                         componentDown();
00051                         delete _socket;
00052                 }
00053 
00054                 dtn::core::Node::Protocol LOWPANConvergenceLayer::getDiscoveryProtocol() const
00055                 {
00056                         return dtn::core::Node::CONN_ZIGBEE; // FIXME CONN_LOWPAN instead?
00057                 }
00058 
00059                 void LOWPANConvergenceLayer::update(std::string &name, std::string &params)
00060                 {
00061                         name = "lowpancl";
00062 
00063                         stringstream service; service << "short address=" << _net.getAddress() << ";panid=" << _panid << ";";
00064                         params = service.str();
00065                 }
00066 
00067                 bool LOWPANConvergenceLayer::onInterface(const ibrcommon::NetInterface &net) const
00068                 {
00069                         if (_net == net) return true;
00070                         return false;
00071                 }
00072 
00073                 void LOWPANConvergenceLayer::queue(const dtn::core::Node &node, const ConvergenceLayer::Job &job)
00074                 {
00075                         std::stringstream ss;
00076                         dtn::data::DefaultSerializer serializer(ss);
00077 
00078                         dtn::core::BundleStorage &storage = dtn::core::BundleCore::getInstance().getStorage();
00079 
00080                         try {
00081                                 // read the bundle out of the storage
00082                                 const dtn::data::Bundle bundle = storage.get(job._bundle);
00083 
00084                                 unsigned int size = serializer.getLength(bundle);
00085 
00086                                 if (size > m_maxmsgsize)
00087                                 {
00088                                         throw ConnectionInterruptedException();
00089                                 }
00090 
00091                                 cout << "CL LOWPAN was asked to connect to " << hex << node.getAddress() << " in PAN " << hex << node.getPort() << endl;
00092 
00093                                 serializer << bundle;
00094                                 string data = ss.str();
00095 
00096                                 // get a lowpan peer //FIXME should be getPan not getPort
00097                                 ibrcommon::lowpansocket::peer p = _socket->getPeer(node.getAddress(), node.getPort());
00098 
00099                                 // set write lock
00100                                 ibrcommon::MutexLock l(m_writelock);
00101 
00102                                 // send converted line back to client.
00103                                 int ret = p.send(data.c_str(), data.length());
00104 
00105                                 if (ret == -1)
00106                                 {
00107                                         // CL is busy, requeue bundle
00108                                         dtn::routing::RequeueBundleEvent::raise(job._destination, job._bundle);
00109 
00110                                         return;
00111                                 }
00112 
00113                                 // raise bundle event
00114                                 dtn::net::TransferCompletedEvent::raise(job._destination, bundle);
00115                                 dtn::core::BundleEvent::raise(bundle, dtn::core::BUNDLE_FORWARDED);
00116                         } catch (const dtn::core::BundleStorage::NoBundleFoundException&) {
00117                                 // send transfer aborted event
00118                                 dtn::net::TransferAbortedEvent::raise(EID(node.getURI()), job._bundle, dtn::net::TransferAbortedEvent::REASON_BUNDLE_DELETED);
00119                         }
00120                 }
00121 
00122                 LOWPANConvergenceLayer& LOWPANConvergenceLayer::operator>>(dtn::data::Bundle &bundle)
00123                 {
00124                         ibrcommon::MutexLock l(m_readlock);
00125 
00126                         char data[m_maxmsgsize];
00127 
00128                         // data waiting
00129                         int len = _socket->receive(data, m_maxmsgsize);
00130 
00131                         if (len > 0)
00132                         {
00133                                 // read all data into a stream
00134                                 stringstream ss;
00135                                 ss.write(data, len);
00136 
00137                                 // get the bundle
00138                                 dtn::data::DefaultDeserializer(ss, dtn::core::BundleCore::getInstance()) >> bundle;
00139                         }
00140 
00141                         return (*this);
00142                 }
00143 
00144                 void LOWPANConvergenceLayer::componentUp()
00145                 {
00146                         try {
00147                                 try {
00148                                         ibrcommon::UnicastSocketLowpan &sock = dynamic_cast<ibrcommon::UnicastSocketLowpan&>(*_socket);
00149                                         sock.bind(_panid, _net);
00150                                 } catch (std::bad_cast) {
00151 
00152                                 }
00153                         } catch (ibrcommon::lowpansocket::SocketException ex) {
00154                                 IBRCOMMON_LOGGER(error) << "Failed to add LOWPAN ConvergenceLayer on " << _net.getAddress() << ":" << _panid << IBRCOMMON_LOGGER_ENDL;
00155                                 IBRCOMMON_LOGGER(error) << "      Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00156                         }
00157                 }
00158 
00159                 void LOWPANConvergenceLayer::componentDown()
00160                 {
00161                         _running = false;
00162                         _socket->shutdown();
00163                         join();
00164                 }
00165 
00166                 void LOWPANConvergenceLayer::componentRun()
00167                 {
00168                         _running = true;
00169 
00170                         while (_running)
00171                         {
00172                                 try {
00173                                         dtn::data::Bundle bundle;
00174                                         (*this) >> bundle;
00175 
00176                                         // determine sender
00177                                         EID sender;
00178 
00179                                         // raise default bundle received event
00180                                         dtn::net::BundleReceivedEvent::raise(sender, bundle);
00181 
00182                                 } catch (dtn::InvalidDataException ex) {
00183                                         IBRCOMMON_LOGGER(warning) << "Received a invalid bundle: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00184                                 } catch (ibrcommon::IOException ex) {
00185 
00186                                 }
00187                                 yield();
00188                         }
00189                 }
00190 
00191                 bool LOWPANConvergenceLayer::__cancellation()
00192                 {
00193                         // since this is an receiving thread we have to cancel the hard way
00194                         return false;
00195                 }
00196 
00197                 const std::string LOWPANConvergenceLayer::getName() const
00198                 {
00199                         return "LOWPANConvergenceLayer";
00200                 }
00201         }
00202 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1