IBR-DTNSuite  0.10
Node.cpp
Go to the documentation of this file.
1 /*
2  * Node.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "core/Node.h"
23 #include "core/BundleCore.h"
24 #include "net/ConvergenceLayer.h"
25 #include <ibrdtn/utils/Clock.h>
26 #include <ibrdtn/utils/Utils.h>
27 #include <ibrcommon/Logger.h>
28 
29 #include <iostream>
30 #include <sstream>
31 
32 using namespace std;
33 
34 namespace dtn
35 {
36  namespace core
37  {
38  Node::URI::URI(const Node::Type t, const Node::Protocol p, const std::string &uri, const dtn::data::Number &to, const int prio)
39  : type(t), protocol(p), value(uri), expire((to == 0) ? 0 : dtn::utils::Clock::getTime() + to), priority(prio)
40  {
41  }
42 
44  {
45  }
46 
47  void Node::URI::decode(std::string &address, unsigned int &port) const
48  {
49  // parse parameters
50  std::vector<string> parameters = dtn::utils::Utils::tokenize(";", value);
51  std::vector<string>::const_iterator param_iter = parameters.begin();
52 
53  while (param_iter != parameters.end())
54  {
55  std::vector<string> p = dtn::utils::Utils::tokenize("=", (*param_iter));
56 
57  if (p[0].compare("ip") == 0)
58  {
59  address = p[1];
60  }
61 
62  if (p[0].compare("port") == 0)
63  {
64  std::stringstream port_stream;
65  port_stream << p[1];
66  port_stream >> port;
67  }
68 
69  ++param_iter;
70  }
71  }
72 
73  bool Node::URI::operator<(const URI &other) const
74  {
75  if (protocol < other.protocol) return true;
76  if (protocol != other.protocol) return false;
77 
78  if (type < other.type) return true;
79  if (type != other.type) return false;
80 
81  return (value < other.value);
82  }
83 
84  bool Node::URI::operator==(const URI &other) const
85  {
86  return ((type == other.type) && (protocol == other.protocol) && (value == other.value));
87  }
88 
90  {
91  return (protocol == p);
92  }
93 
94  bool Node::URI::operator==(const Node::Type &t) const
95  {
96  return (type == t);
97  }
98 
99  std::ostream& operator<<(std::ostream &stream, const Node::URI &u)
100  {
101  stream << u.priority << "#" << Node::toString(u.type) << "#" << Node::toString(u.protocol) << "#" << u.value;
102  return stream;
103  }
104 
105  Node::Attribute::Attribute(const Type t, const std::string &n, const std::string &v, const dtn::data::Number &to, const int p)
106  : type(t), name(n), value(v), expire((to == 0) ? 0 : dtn::utils::Clock::getTime() + to), priority(p)
107  {
108  }
109 
111  {
112  }
113 
114  bool Node::Attribute::operator<(const Attribute &other) const
115  {
116  if (name < other.name) return true;
117  if (name != other.name) return false;
118 
119  return (type < other.type);
120  }
121 
122  bool Node::Attribute::operator==(const Attribute &other) const
123  {
124  return ((type == other.type) && (name == other.name));
125  }
126 
127  bool Node::Attribute::operator==(const std::string &n) const
128  {
129  return (name == n);
130  }
131 
132  std::ostream& operator<<(std::ostream &stream, const Node::Attribute &a)
133  {
134  stream << a.priority << "#" << Node::toString(a.type) << "#" << a.name << "#" << a.value;
135  return stream;
136  }
137 
139  : _connect_immediately(false), _id(), _announced_mark(false)
140  {
141  }
142 
144  : _connect_immediately(false), _id(id), _announced_mark(false)
145  {
146  }
147 
149  {
150  }
151 
152  std::string Node::toString(const Node::Type type)
153  {
154  switch (type)
155  {
157  return "unavailable";
158 
160  return "discovered";
161 
163  return "static global";
164 
166  return "static local";
167 
169  return "connected";
170 
172  return "dht discovered";
173 
175  return "p2p dialup";
176  }
177 
178  return "unknown";
179  }
180 
181  std::string Node::toString(const Node::Protocol proto)
182  {
183  switch (proto)
184  {
186  return "unsupported";
187 
189  return "undefined";
190 
191  case Node::CONN_UDPIP:
192  return "UDP";
193 
194  case Node::CONN_TCPIP:
195  return "TCP";
196 
197  case Node::CONN_LOWPAN:
198  return "LoWPAN";
199 
201  return "Bluetooth";
202 
203  case Node::CONN_HTTP:
204  return "HTTP";
205 
206  case Node::CONN_FILE:
207  return "FILE";
208 
210  return "DGRAM:UDP";
211 
213  return "DGRAM:ETHERNET";
214 
216  return "DGRAM:LOWPAN";
217 
218  case Node::CONN_P2P_WIFI:
219  return "P2P:WIFI";
220 
221  case Node::CONN_P2P_BT:
222  return "P2P:BT";
223  }
224 
225  return "unknown";
226  }
227 
228  Node::Protocol Node::fromProtocolString(const std::string &protocol)
229  {
230  if (protocol == "UDP") {
231  return Node::CONN_UDPIP;
232  } else if (protocol == "TCP") {
233  return Node::CONN_TCPIP;
234  } else if (protocol == "LoWPAN") {
235  return Node::CONN_LOWPAN;
236  } else if (protocol == "Bluetooth") {
237  return Node::CONN_BLUETOOTH;
238  } else if (protocol == "HTTP") {
239  return Node::CONN_HTTP;
240  } else if (protocol == "FILE") {
241  return Node::CONN_FILE;
242  } else if (protocol == "DGRAM:UDP") {
243  return Node::CONN_DGRAM_UDP;
244  } else if (protocol == "DGRAM:ETHERNET") {
246  } else if (protocol == "DGRAM:LOWPAN") {
248  } else if (protocol == "P2P:WIFI") {
249  return Node::CONN_P2P_WIFI;
250  } else if (protocol == "unsupported") {
251  return Node::CONN_P2P_BT;
252  } else if (protocol == "unsupported") {
253  return Node::CONN_UNSUPPORTED;
254  }
255 
256  return Node::CONN_UNDEFINED;
257  }
258 
259  bool Node::has(Node::Protocol proto) const
260  {
261  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
262  {
263  if ((*iter) == proto) return true;
264  }
265  return false;
266  }
267 
268  bool Node::has(const std::string &name) const
269  {
270  for (std::set<Attribute>::const_iterator iter = _attr_list.begin(); iter != _attr_list.end(); ++iter)
271  {
272  if ((*iter) == name) return true;
273  }
274  return false;
275  }
276 
277  void Node::add(const URI &u)
278  {
279  _uri_list.erase(u);
280  _uri_list.insert(u);
281  }
282 
283  void Node::add(const Attribute &attr)
284  {
285  _attr_list.erase(attr);
286  _attr_list.insert(attr);
287  }
288 
289  void Node::remove(const URI &u)
290  {
291  _uri_list.erase(u);
292  }
293 
294  void Node::remove(const Attribute &attr)
295  {
296  _attr_list.erase(attr);
297  }
298 
299  void Node::clear()
300  {
301  _uri_list.clear();
302  _attr_list.clear();
303  }
304 
306  {
307  return _uri_list.size() + _attr_list.size();
308  }
309 
310  // comparison of two URIs according to the priority
311  bool compare_uri_priority (const Node::URI &first, const Node::URI &second)
312  {
313  return first.priority > second.priority;
314  }
315 
316  // comparison of two Attributes according to the priority
317  bool compare_attr_priority (const Node::Attribute &first, const Node::Attribute &second)
318  {
319  return first.priority > second.priority;
320  }
321 
322  std::list<Node::URI> Node::get(Node::Protocol proto) const
323  {
324  std::list<URI> ret;
325  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
326  {
327  const URI &uri = (*iter);
328 
329  if ((uri == proto) && isAvailable(uri))
330  {
331  ret.push_back(uri);
332  }
333  }
334 
335  ret.sort(compare_uri_priority);
336  return ret;
337  }
338 
339  std::list<Node::URI> Node::get(Node::Type type) const
340  {
341  std::list<URI> ret;
342  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
343  {
344  const URI &uri = (*iter);
345 
346  if (uri == type)
347  {
348  ret.push_back(uri);
349  }
350  }
351 
352  ret.sort(compare_uri_priority);
353  return ret;
354  }
355 
356  std::list<Node::URI> Node::get(Node::Type type, Node::Protocol proto) const
357  {
358  std::list<URI> ret;
359  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
360  {
361  const URI &uri = (*iter);
362 
363  if ((uri == proto) && (uri == type) && isAvailable(uri)) ret.push_back(uri);
364  }
365  ret.sort(compare_uri_priority);
366  return ret;
367  }
368 
369  std::list<Node::URI> Node::getAll() const
370  {
371  std::list<Node::URI> ret;
372  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
373  {
374  const URI &uri = (*iter);
375 
376  if (isAvailable(uri)) ret.push_back(uri);
377  }
378  ret.sort(compare_uri_priority);
379  return ret;
380  }
381 
382  std::set<Node::Type> Node::getTypes() const
383  {
384  std::set<Type> ret;
385  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
386  {
387  ret.insert((*iter).type);
388  }
389  return ret;
390  }
391 
392  std::list<Node::Attribute> Node::get(const std::string &name) const
393  {
394  std::list<Attribute> ret;
395  for (std::set<Attribute>::const_iterator iter = _attr_list.begin(); iter != _attr_list.end(); ++iter)
396  {
397  if ((*iter) == name) ret.push_back(*iter);
398  }
399  ret.sort(compare_attr_priority);
400  return ret;
401  }
402 
404  {
405  return _id;
406  }
407 
413  {
414  // get the current timestamp
416 
417  // walk though all Attribute elements and remove the expired ones
418  {
419  std::set<Attribute>::iterator iter = _attr_list.begin();
420  while ( iter != _attr_list.end() )
421  {
422  const Attribute &attr = (*iter);
423  if ((attr.expire > 0) && (attr.expire < ct))
424  {
425  // remove this attribute
426  _attr_list.erase(iter++);
427  }
428  else
429  {
430  ++iter;
431  }
432  }
433  }
434 
435  // walk though all URI elements and remove the expired ones
436  {
437  std::set<URI>::iterator iter = _uri_list.begin();
438  while ( iter != _uri_list.end() )
439  {
440  const URI &u = (*iter);
441  if ((u.expire > 0) && (u.expire < ct))
442  {
443  // remove this attribute
444  _uri_list.erase(iter++);
445  }
446  else
447  {
448  ++iter;
449  }
450  }
451  }
452 
453  return (_attr_list.empty() && _uri_list.empty());
454  }
455 
456  const Node& Node::operator+=(const Node &other)
457  {
458  for (std::set<Attribute>::const_iterator iter = other._attr_list.begin(); iter != other._attr_list.end(); ++iter)
459  {
460  const Attribute &attr = (*iter);
461  add(attr);
462  }
463 
464  for (std::set<URI>::const_iterator iter = other._uri_list.begin(); iter != other._uri_list.end(); ++iter)
465  {
466  const URI &u = (*iter);
467  add(u);
468  }
469 
470  return (*this);
471  }
472 
473  const Node& Node::operator-=(const Node &other)
474  {
475  for (std::set<Attribute>::const_iterator iter = other._attr_list.begin(); iter != other._attr_list.end(); ++iter)
476  {
477  const Attribute &attr = (*iter);
478  remove(attr);
479  }
480 
481  for (std::set<URI>::const_iterator iter = other._uri_list.begin(); iter != other._uri_list.end(); ++iter)
482  {
483  const URI &u = (*iter);
484  remove(u);
485  }
486 
487  return (*this);
488  }
489 
490  bool Node::operator==(const dtn::data::EID &other) const
491  {
492  return (other == _id);
493  }
494 
495  bool Node::operator==(const Node &other) const
496  {
497  return (other._id == _id);
498  }
499 
500  bool Node::operator<(const Node &other) const
501  {
502  if (_id < other._id ) return true;
503 
504  return false;
505  }
506 
507  std::string Node::toString() const
508  {
509  std::stringstream ss; ss << getEID().getString();
510  return ss.str();
511  }
512 
514  {
515  return _connect_immediately;
516  }
517 
519  {
520  _connect_immediately = val;
521  }
522 
523  bool Node::hasDialup() const
524  {
525  for (std::set<Node::URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
526  {
527  const Node::URI &u = (*iter);
528  if (u.type == NODE_P2P_DIALUP) return true;
529  }
530 
531  return false;
532  }
533 
534  bool Node::isAvailable() const
535  {
536  if (dtn::core::BundleCore::getInstance().isGloballyConnected()) {
537  return !_uri_list.empty();
538  } else {
539  // filter for global addresses when internet is not available
540  for (std::set<Node::URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
541  {
542  const Node::URI &u = (*iter);
543 
544  switch (u.type) {
545  case NODE_CONNECTED: return true;
546  case NODE_DISCOVERED: return true;
547  case NODE_STATIC_LOCAL: return true;
548  case NODE_P2P_DIALUP: return true;
549  default: break;
550  }
551  }
552  }
553 
554  return false;
555  }
556 
557  bool Node::isAvailable(const Node::URI &uri) const
558  {
559  if (dtn::core::BundleCore::getInstance().isGloballyConnected()) {
560  return true;
561  } else {
562  switch (uri.type)
563  {
564  case NODE_CONNECTED:
565  return true;
566 
567  case NODE_DISCOVERED:
568  return true;
569 
570  case NODE_STATIC_LOCAL:
571  return true;
572 
573  case NODE_P2P_DIALUP:
574  return true;
575 
576  default:
577  return false;
578  }
579  }
580  }
581 
582  void Node::setAnnounced(bool val)
583  {
584  _announced_mark = val;
585  }
586 
587  bool Node::isAnnounced() const
588  {
589  return _announced_mark;
590  }
591 
592  std::ostream& operator<<(std::ostream &stream, const Node &node)
593  {
594  stream << "Node: " << node._id.getString() << " [ ";
595  for (std::set<Node::Attribute>::const_iterator iter = node._attr_list.begin(); iter != node._attr_list.end(); ++iter)
596  {
597  const Node::Attribute &attr = (*iter);
598  stream << attr << "#expire=" << attr.expire.toString() << "; ";
599  }
600 
601  for (std::set<Node::URI>::const_iterator iter = node._uri_list.begin(); iter != node._uri_list.end(); ++iter)
602  {
603  const Node::URI &u = (*iter);
604  stream << u << "#expire=" << u.expire.toString() << "; ";
605  }
606  stream << " ]";
607 
608  return stream;
609  }
610  }
611 }