IBR-DTNSuite  0.12
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 || p[0].compare("email") == 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  case Node::CONN_EMAIL:
225  return "EMAIL";
226  }
227 
228  return "unknown";
229  }
230 
231  Node::Protocol Node::fromProtocolString(const std::string &protocol)
232  {
233  if (protocol == "UDP") {
234  return Node::CONN_UDPIP;
235  } else if (protocol == "TCP") {
236  return Node::CONN_TCPIP;
237  } else if (protocol == "LoWPAN") {
238  return Node::CONN_LOWPAN;
239  } else if (protocol == "Bluetooth") {
240  return Node::CONN_BLUETOOTH;
241  } else if (protocol == "HTTP") {
242  return Node::CONN_HTTP;
243  } else if (protocol == "FILE") {
244  return Node::CONN_FILE;
245  } else if (protocol == "DGRAM:UDP") {
246  return Node::CONN_DGRAM_UDP;
247  } else if (protocol == "DGRAM:ETHERNET") {
249  } else if (protocol == "DGRAM:LOWPAN") {
251  } else if (protocol == "P2P:WIFI") {
252  return Node::CONN_P2P_WIFI;
253  } else if (protocol == "unsupported") {
254  return Node::CONN_P2P_BT;
255  } else if (protocol == "unsupported") {
256  return Node::CONN_UNSUPPORTED;
257  }
258 
259  return Node::CONN_UNDEFINED;
260  }
261 
262  bool Node::has(Node::Protocol proto) const
263  {
264  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
265  {
266  if ((*iter) == proto) return true;
267  }
268  return false;
269  }
270 
271  bool Node::has(const std::string &name) const
272  {
273  for (std::set<Attribute>::const_iterator iter = _attr_list.begin(); iter != _attr_list.end(); ++iter)
274  {
275  if ((*iter) == name) return true;
276  }
277  return false;
278  }
279 
280  void Node::add(const URI &u)
281  {
282  _uri_list.erase(u);
283  _uri_list.insert(u);
284  }
285 
286  void Node::add(const Attribute &attr)
287  {
288  _attr_list.erase(attr);
289  _attr_list.insert(attr);
290  }
291 
292  void Node::remove(const URI &u)
293  {
294  _uri_list.erase(u);
295  }
296 
297  void Node::remove(const Attribute &attr)
298  {
299  _attr_list.erase(attr);
300  }
301 
302  void Node::clear()
303  {
304  _uri_list.clear();
305  _attr_list.clear();
306  }
307 
309  {
310  return _uri_list.size() + _attr_list.size();
311  }
312 
313  // comparison of two URIs according to the priority
314  bool compare_uri_priority (const Node::URI &first, const Node::URI &second)
315  {
316  return first.priority > second.priority;
317  }
318 
319  // comparison of two Attributes according to the priority
320  bool compare_attr_priority (const Node::Attribute &first, const Node::Attribute &second)
321  {
322  return first.priority > second.priority;
323  }
324 
325  std::list<Node::URI> Node::get(Node::Protocol proto) const
326  {
327  std::list<URI> ret;
328  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
329  {
330  const URI &uri = (*iter);
331 
332  if ((uri == proto) && isAvailable(uri))
333  {
334  ret.push_back(uri);
335  }
336  }
337 
338  ret.sort(compare_uri_priority);
339  return ret;
340  }
341 
342  std::list<Node::URI> Node::get(Node::Type type) const
343  {
344  std::list<URI> ret;
345  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
346  {
347  const URI &uri = (*iter);
348 
349  if (uri == type)
350  {
351  ret.push_back(uri);
352  }
353  }
354 
355  ret.sort(compare_uri_priority);
356  return ret;
357  }
358 
359  std::list<Node::URI> Node::get(Node::Type type, Node::Protocol proto) const
360  {
361  std::list<URI> ret;
362  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
363  {
364  const URI &uri = (*iter);
365 
366  if ((uri == proto) && (uri == type) && isAvailable(uri)) ret.push_back(uri);
367  }
368  ret.sort(compare_uri_priority);
369  return ret;
370  }
371 
372  std::list<Node::URI> Node::getAll() const
373  {
374  std::list<Node::URI> ret;
375  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
376  {
377  const URI &uri = (*iter);
378 
379  if (isAvailable(uri)) ret.push_back(uri);
380  }
381  ret.sort(compare_uri_priority);
382  return ret;
383  }
384 
385  std::set<Node::Type> Node::getTypes() const
386  {
387  std::set<Type> ret;
388  for (std::set<URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
389  {
390  ret.insert((*iter).type);
391  }
392  return ret;
393  }
394 
395  std::list<Node::Attribute> Node::get(const std::string &name) const
396  {
397  std::list<Attribute> ret;
398  for (std::set<Attribute>::const_iterator iter = _attr_list.begin(); iter != _attr_list.end(); ++iter)
399  {
400  if ((*iter) == name) ret.push_back(*iter);
401  }
402  ret.sort(compare_attr_priority);
403  return ret;
404  }
405 
407  {
408  return _id;
409  }
410 
416  {
417  // get the current timestamp
419 
420  // walk though all Attribute elements and remove the expired ones
421  {
422  std::set<Attribute>::iterator iter = _attr_list.begin();
423  while ( iter != _attr_list.end() )
424  {
425  const Attribute &attr = (*iter);
426  if ((attr.expire > 0) && (attr.expire < ct))
427  {
428  // remove this attribute
429  _attr_list.erase(iter++);
430  }
431  else
432  {
433  ++iter;
434  }
435  }
436  }
437 
438  // walk though all URI elements and remove the expired ones
439  {
440  std::set<URI>::iterator iter = _uri_list.begin();
441  while ( iter != _uri_list.end() )
442  {
443  const URI &u = (*iter);
444  if ((u.expire > 0) && (u.expire < ct))
445  {
446  // remove this attribute
447  _uri_list.erase(iter++);
448  }
449  else
450  {
451  ++iter;
452  }
453  }
454  }
455 
456  return (_attr_list.empty() && _uri_list.empty());
457  }
458 
459  const Node& Node::operator+=(const Node &other)
460  {
461  for (std::set<Attribute>::const_iterator iter = other._attr_list.begin(); iter != other._attr_list.end(); ++iter)
462  {
463  const Attribute &attr = (*iter);
464  add(attr);
465  }
466 
467  for (std::set<URI>::const_iterator iter = other._uri_list.begin(); iter != other._uri_list.end(); ++iter)
468  {
469  const URI &u = (*iter);
470  add(u);
471  }
472 
473  return (*this);
474  }
475 
476  const Node& Node::operator-=(const Node &other)
477  {
478  for (std::set<Attribute>::const_iterator iter = other._attr_list.begin(); iter != other._attr_list.end(); ++iter)
479  {
480  const Attribute &attr = (*iter);
481  remove(attr);
482  }
483 
484  for (std::set<URI>::const_iterator iter = other._uri_list.begin(); iter != other._uri_list.end(); ++iter)
485  {
486  const URI &u = (*iter);
487  remove(u);
488  }
489 
490  return (*this);
491  }
492 
493  bool Node::operator==(const dtn::data::EID &other) const
494  {
495  return (other == _id);
496  }
497 
498  bool Node::operator==(const Node &other) const
499  {
500  return (other._id == _id);
501  }
502 
503  bool Node::operator<(const Node &other) const
504  {
505  if (_id < other._id ) return true;
506 
507  return false;
508  }
509 
510  std::string Node::toString() const
511  {
512  std::stringstream ss; ss << getEID().getString();
513  return ss.str();
514  }
515 
517  {
518  return _connect_immediately;
519  }
520 
522  {
523  _connect_immediately = val;
524  }
525 
526  bool Node::hasDialup() const
527  {
528  for (std::set<Node::URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
529  {
530  const Node::URI &u = (*iter);
531  if (u.type == NODE_P2P_DIALUP) return true;
532  }
533 
534  return false;
535  }
536 
537  bool Node::isAvailable() const
538  {
539  if (dtn::core::BundleCore::getInstance().isGloballyConnected()) {
540  return !_uri_list.empty();
541  } else {
542  // filter for global addresses when internet is not available
543  for (std::set<Node::URI>::const_iterator iter = _uri_list.begin(); iter != _uri_list.end(); ++iter)
544  {
545  const Node::URI &u = (*iter);
546 
547  switch (u.type) {
548  case NODE_CONNECTED: return true;
549  case NODE_DISCOVERED: return true;
550  case NODE_STATIC_LOCAL: return true;
551  case NODE_P2P_DIALUP: return true;
552  default: break;
553  }
554  }
555  }
556 
557  return false;
558  }
559 
560  bool Node::isAvailable(const Node::URI &uri) const
561  {
562  if (dtn::core::BundleCore::getInstance().isGloballyConnected()) {
563  return true;
564  } else {
565  switch (uri.type)
566  {
567  case NODE_CONNECTED:
568  return true;
569 
570  case NODE_DISCOVERED:
571  return true;
572 
573  case NODE_STATIC_LOCAL:
574  return true;
575 
576  case NODE_P2P_DIALUP:
577  return true;
578 
579  default:
580  return false;
581  }
582  }
583  }
584 
585  void Node::setAnnounced(bool val)
586  {
587  _announced_mark = val;
588  }
589 
590  bool Node::isAnnounced() const
591  {
592  return _announced_mark;
593  }
594 
595  std::ostream& operator<<(std::ostream &stream, const Node &node)
596  {
597  stream << "Node: " << node._id.getString() << " [ ";
598  for (std::set<Node::Attribute>::const_iterator iter = node._attr_list.begin(); iter != node._attr_list.end(); ++iter)
599  {
600  const Node::Attribute &attr = (*iter);
601  stream << attr << "#expire=" << attr.expire.toString() << "; ";
602  }
603 
604  for (std::set<Node::URI>::const_iterator iter = node._uri_list.begin(); iter != node._uri_list.end(); ++iter)
605  {
606  const Node::URI &u = (*iter);
607  stream << u << "#expire=" << u.expire.toString() << "; ";
608  }
609  stream << " ]";
610 
611  return stream;
612  }
613  }
614 }