IBR-DTNSuite
0.8
|
00001 #include "net/LOWPANConvergenceLayer.h" 00002 #include "net/LOWPANConnection.h" 00003 #include "core/BundleCore.h" 00004 #include "core/TimeEvent.h" 00005 #include <ibrcommon/net/lowpanstream.h> 00006 #include <ibrcommon/net/UnicastSocketLowpan.h> 00007 #include <ibrcommon/net/lowpansocket.h> 00008 00009 #include <ibrcommon/Logger.h> 00010 #include <ibrcommon/thread/MutexLock.h> 00011 #include <ibrcommon/TimeMeasurement.h> 00012 00013 #include <sys/socket.h> 00014 #include <stdlib.h> 00015 #include <stdio.h> 00016 #include <string.h> 00017 00018 #include <iostream> 00019 #include <list> 00020 00021 #define EXTENDED_MASK 0x08 00022 #define SEQ_NUM_MASK 0x07 00023 00024 using namespace dtn::data; 00025 00026 namespace dtn 00027 { 00028 namespace net 00029 { 00030 LOWPANConvergenceLayer::LOWPANConvergenceLayer(ibrcommon::vinterface net, int panid, unsigned int mtu) 00031 : DiscoveryAgent(dtn::daemon::Configuration::getInstance().getDiscovery()), 00032 _socket(NULL), _net(net), _panid(panid), _ipnd_buf(new char[BUFF_SIZE+2]), _ipnd_buf_len(0), m_maxmsgsize(mtu), _running(false) 00033 { 00034 _socket = new ibrcommon::UnicastSocketLowpan(); 00035 } 00036 00037 LOWPANConvergenceLayer::~LOWPANConvergenceLayer() 00038 { 00039 componentDown(); 00040 delete _socket; 00041 } 00042 00043 dtn::core::Node::Protocol LOWPANConvergenceLayer::getDiscoveryProtocol() const 00044 { 00045 return dtn::core::Node::CONN_LOWPAN; 00046 } 00047 00048 void LOWPANConvergenceLayer::update(const ibrcommon::vinterface &iface, std::string &name, std::string ¶ms) throw(dtn::net::DiscoveryServiceProvider::NoServiceHereException) 00049 { 00050 if (iface == _net) 00051 { 00052 name = "lowpancl"; 00053 stringstream service; 00054 00055 struct sockaddr_ieee802154 address; 00056 address.addr.addr_type = IEEE802154_ADDR_SHORT; 00057 address.addr.pan_id = _panid; 00058 00059 // Get address via netlink 00060 ibrcommon::lowpansocket::getAddress(&address.addr, iface); 00061 00062 //FIXME better naming for address and panid. This will need updates to the service parser. 00063 service << "ip=" << address.addr.short_addr << ";port=" << _panid << ";"; 00064 00065 params = service.str(); 00066 } 00067 else 00068 { 00069 throw dtn::net::DiscoveryServiceProvider::NoServiceHereException(); 00070 } 00071 } 00072 00073 void LOWPANConvergenceLayer::send_cb(char *buf, int len, unsigned int address) 00074 { 00075 // Add own address at the end 00076 struct sockaddr_ieee802154 _sockaddr; 00077 unsigned short local_addr; 00078 00079 _socket->getAddress(&_sockaddr.addr, _net); 00080 00081 local_addr = _sockaddr.addr.short_addr; 00082 00083 // get a lowpan peer 00084 ibrcommon::lowpansocket::peer p = _socket->getPeer(address, _sockaddr.addr.pan_id); 00085 if (len > 113) 00086 IBRCOMMON_LOGGER(error) << "LOWPANConvergenceLayer::send_cb buffer to big to be transferred (" << len << ")."<< IBRCOMMON_LOGGER_ENDL; 00087 00088 // Add own address at the end 00089 memcpy(&buf[len], &local_addr, 2); 00090 00091 // set write lock 00092 ibrcommon::MutexLock l(m_writelock); 00093 00094 // send converted line 00095 int ret = p.send(buf, len + 2); 00096 00097 if (ret == -1) 00098 { 00099 // CL is busy 00100 throw(ibrcommon::Exception("Send on socket failed")); 00101 } 00102 } 00103 00104 void LOWPANConvergenceLayer::queue(const dtn::core::Node &node, const ConvergenceLayer::Job &job) 00105 { 00106 const std::list<dtn::core::Node::URI> uri_list = node.get(dtn::core::Node::CONN_LOWPAN); 00107 if (uri_list.empty()) return; 00108 00109 const dtn::core::Node::URI &uri = uri_list.front(); 00110 00111 std::string address; 00112 unsigned int pan; 00113 00114 uri.decode(address, pan); 00115 00116 IBRCOMMON_LOGGER_DEBUG(10) << "LOWPANConvergenceLayer::queue"<< IBRCOMMON_LOGGER_ENDL; 00117 00118 ibrcommon::MutexLock lc(_connection_lock); 00119 getConnection(atoi(address.c_str()))->_sender.queue(job); 00120 } 00121 00122 LOWPANConnection* LOWPANConvergenceLayer::getConnection(unsigned short address) 00123 { 00124 // Test if connection for this address already exist 00125 std::list<LOWPANConnection*>::iterator i; 00126 for(i = ConnectionList.begin(); i != ConnectionList.end(); ++i) 00127 { 00128 IBRCOMMON_LOGGER_DEBUG(10) << "Connection address: " << hex << (*i)->_address << IBRCOMMON_LOGGER_ENDL; 00129 if ((*i)->_address == address) 00130 return (*i); 00131 } 00132 00133 // Connection does not exist, create one and put it into the list 00134 LOWPANConnection *connection = new LOWPANConnection(address, (*this)); 00135 00136 ConnectionList.push_back(connection); 00137 IBRCOMMON_LOGGER_DEBUG(10) << "LOWPANConvergenceLayer::getConnection "<< connection->_address << IBRCOMMON_LOGGER_ENDL; 00138 connection->start(); 00139 return connection; 00140 } 00141 00142 void LOWPANConvergenceLayer::remove(const LOWPANConnection *conn) 00143 { 00144 ibrcommon::MutexLock lc(_connection_lock); 00145 00146 std::list<LOWPANConnection*>::iterator i; 00147 for(i = ConnectionList.begin(); i != ConnectionList.end(); ++i) 00148 { 00149 if ((*i) == conn) 00150 { 00151 ConnectionList.erase(i); 00152 return; 00153 } 00154 } 00155 } 00156 00157 void LOWPANConvergenceLayer::componentUp() 00158 { 00159 bindEvent(dtn::core::TimeEvent::className); 00160 try { 00161 try { 00162 ibrcommon::UnicastSocketLowpan &sock = dynamic_cast<ibrcommon::UnicastSocketLowpan&>(*_socket); 00163 sock.bind(_panid, _net); 00164 00165 addService(this); 00166 } catch (const std::bad_cast&) { 00167 00168 } 00169 } catch (const ibrcommon::lowpansocket::SocketException &ex) { 00170 IBRCOMMON_LOGGER_DEBUG(10) << "Failed to add LOWPAN ConvergenceLayer on " << _net.toString() << ":" << _panid << IBRCOMMON_LOGGER_ENDL; 00171 IBRCOMMON_LOGGER_DEBUG(10) << "Exception: " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00172 } 00173 } 00174 00175 void LOWPANConvergenceLayer::componentDown() 00176 { 00177 unbindEvent(dtn::core::TimeEvent::className); 00178 stop(); 00179 join(); 00180 } 00181 00182 void LOWPANConvergenceLayer::sendAnnoucement(const u_int16_t &sn, std::list<dtn::net::DiscoveryService> &services) 00183 { 00184 IBRCOMMON_LOGGER_DEBUG(10) << "LOWPAN IPND beacon send started" << IBRCOMMON_LOGGER_ENDL; 00185 00186 DiscoveryAnnouncement announcement(DiscoveryAnnouncement::DISCO_VERSION_01, dtn::core::BundleCore::local); 00187 00188 // set sequencenumber 00189 announcement.setSequencenumber(sn); 00190 00191 // clear all services 00192 announcement.clearServices(); 00193 00194 // add services 00195 for (std::list<DiscoveryService>::iterator iter = services.begin(); iter != services.end(); iter++) 00196 { 00197 DiscoveryService &service = (*iter); 00198 00199 try { 00200 // update service information 00201 service.update(_net); 00202 00203 // add service to discovery message 00204 announcement.addService(service); 00205 } catch (const dtn::net::DiscoveryServiceProvider::NoServiceHereException&) { 00206 00207 } 00208 } 00209 // Set extended header bit. Everything else 0 00210 _ipnd_buf[0] = 0x08; 00211 // Set discovery bit in extended header 00212 _ipnd_buf[1] = 0x80; 00213 00214 // serialize announcement 00215 stringstream ss; 00216 ss << announcement; 00217 00218 int len = ss.str().size(); 00219 if (len > 111) 00220 IBRCOMMON_LOGGER(error) << "Discovery announcement to big (" << len << ")" << IBRCOMMON_LOGGER_ENDL; 00221 00222 memcpy(_ipnd_buf+2, ss.str().c_str(), len); 00223 00224 send_cb(_ipnd_buf, len + 2, 0xffff); 00225 } 00226 00227 void LOWPANConvergenceLayer::componentRun() 00228 { 00229 _running = true; 00230 00231 while (_running) 00232 { 00233 ibrcommon::MutexLock l(m_readlock); 00234 00235 char data[m_maxmsgsize]; 00236 char header; 00237 unsigned short address; 00238 00239 IBRCOMMON_LOGGER_DEBUG(10) << "LOWPANConvergenceLayer::componentRun early" << IBRCOMMON_LOGGER_ENDL; 00240 00241 // Receive full frame from socket 00242 int len = _socket->receive(data, m_maxmsgsize); 00243 00244 IBRCOMMON_LOGGER_DEBUG(10) << "LOWPANConvergenceLayer::componentRun" << IBRCOMMON_LOGGER_ENDL; 00245 00246 // We got nothing from the socket, keep reading 00247 if (len <= 0) 00248 continue; 00249 00250 // Retrieve header of frame 00251 header = data[0]; 00252 00253 // Retrieve sender address from the end of the frame 00254 address = ((char)data[len-1] << 8) | data[len-2]; 00255 00256 // Check for extended header and retrieve if available 00257 if ((header & EXTENDED_MASK) && (data[1] & 0x80)) { 00258 IBRCOMMON_LOGGER_DEBUG(10) << "Received announcement for LoWPAN discovery: ADDRESS " << address << IBRCOMMON_LOGGER_ENDL; 00259 DiscoveryAnnouncement announce; 00260 stringstream ss; 00261 ss.write(data+2, len-4); 00262 ss >> announce; 00263 DiscoveryAgent::received(announce, 30); 00264 continue; 00265 } 00266 00267 ibrcommon::MutexLock lc(_connection_lock); 00268 00269 // Connection instance for this address 00270 LOWPANConnection* connection = getConnection(address); 00271 00272 // Decide in which queue to write based on the src address 00273 connection->getStream().queue(data, len-2); // Cut off address from end 00274 00275 yield(); 00276 } 00277 } 00278 00279 void LOWPANConvergenceLayer::raiseEvent(const Event *evt) 00280 { 00281 try { 00282 const TimeEvent &time=dynamic_cast<const TimeEvent&>(*evt); 00283 if (time.getAction() == TIME_SECOND_TICK) 00284 if (time.getTimestamp()%5 == 0) 00285 timeout(); 00286 } catch (const std::bad_cast&) 00287 {} 00288 } 00289 00290 void LOWPANConvergenceLayer::__cancellation() 00291 { 00292 _running = false; 00293 _socket->shutdown(); 00294 } 00295 00296 const std::string LOWPANConvergenceLayer::getName() const 00297 { 00298 return "LOWPANConvergenceLayer"; 00299 } 00300 } 00301 }