IBR-DTNSuite 0.6

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