IBR-DTNSuite  0.12
EID.cpp
Go to the documentation of this file.
1 /*
2  * EID.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 "ibrdtn/config.h"
23 #include "ibrdtn/data/EID.h"
24 #include "ibrdtn/utils/Utils.h"
25 #include <sstream>
26 #include <iostream>
27 
28 #ifdef HAVE_OPENSSL
29 #include <openssl/md5.h>
30 #endif
31 
32 // include code for platform-independent endianess conversion
33 #include "ibrdtn/data/Endianess.h"
34 
35 namespace dtn
36 {
37  namespace data
38  {
39  // static initialization of the CBHE map
40  EID::cbhe_map& EID::getApplicationMap()
41  {
42  static cbhe_map app_map;
43 
44  // initialize the application map
45  if (app_map.empty()) {
46  app_map["null"] = 1;
47  app_map["debugger"] = 2;
48  app_map["bundle-in-bundle"] = 5;
49  app_map["echo"] = 11;
50  app_map["routing"] = 50;
51  app_map["dtntp"] = 60;
52  }
53 
54  return app_map;
55  }
56 
57  const std::string EID::getSchemeName(const Scheme s)
58  {
59  switch (s) {
60  case SCHEME_DTN:
61  return "dtn";
62  case SCHEME_CBHE:
63  return "ipn";
64  default:
65  return "";
66  }
67  }
68 
69  EID::Scheme EID::resolveScheme(const std::string &s)
70  {
71  if ("dtn" == s) {
72  return SCHEME_DTN;
73  }
74  else if ("ipn" == s) {
75  return SCHEME_CBHE;
76  }
77  else {
78  return SCHEME_EXTENDED;
79  }
80  }
81 
82  void EID::extractCBHE(const std::string &ssp, Number &node, Number &app)
83  {
84  char delimiter = '\0';
85 
86  size_t n = 0;
87  size_t a = 0;
88 
89  std::stringstream ss(ssp);
90  ss >> n;
91  node = n;
92 
93  ss.get(delimiter);
94 
95  if (delimiter == '.') {
96  ss >> a;
97  app = a;
98  } else {
99  app = 0;
100  }
101  }
102 
103  void EID::extractDTN(const std::string &ssp, std::string &node, std::string &application)
104  {
105  size_t first_char = 0;
106  const char delimiter = '/';
107 
108  // first char not "/", e.g. "//node1" -> 2
109  first_char = ssp.find_first_not_of(delimiter);
110 
111  // only "/" ? thats bad!
112  if (first_char == std::string::npos) {
113  node = "none";
114  application = "";
115  return;
116  }
117 
118  // start of application part
119  size_t application_start = ssp.find_first_of(delimiter, first_char);
120 
121  // no application part available
122  if (application_start == std::string::npos) {
123  node = ssp;
124  application = "";
125  return;
126  }
127 
128  // set the node part
129  node = ssp.substr(0, application_start);
130 
131  // set the application part
132  application = ssp.substr(application_start + 1, ssp.length() - application_start - 1);
133  }
134 
135  Number EID::getApplicationNumber(const std::string &app)
136  {
137  // an empty string returns zero
138  if (app.empty()) return 0;
139 
140  // check if the string is a number
141  std::string::const_iterator char_it = app.begin();
142  while (char_it != app.end() && std::isdigit(*char_it)) ++char_it;
143 
144  if (char_it == app.end()) {
145  // the string contains only digits
146  Number ret;
147 
148  // convert the string into a number
149  std::stringstream ss(app);
150  ret.read(ss);
151 
152  return ret;
153  }
154 
155  // ask the well-known numbers
156  const cbhe_map &m = getApplicationMap();
157 
158  // search for the application in the map
159  cbhe_map::const_iterator it = m.find(app);
160 
161  // if there is a standard mapping
162  if (it != m.end()) {
163  // return the standard number
164  return (*it).second;
165  }
166 
167  // there is no standard mapping, hash required
168 #ifdef HAVE_OPENSSL
169  std::vector<unsigned char> hash(MD5_DIGEST_LENGTH);
170  MD5((unsigned char*)app.c_str(), app.length(), &hash[0]);
171 
172  // use 4 byte as integer
173  uint32_t number = GUINT32_TO_BE((uint32_t&)hash[0]);
174 
175  // set the highest bit
176  number |= 0x80000000;
177 
178  return Number(number);
179 #else
180  return 0;
181 #endif
182  }
183 
185  : _scheme_type(SCHEME_DTN), _scheme(), _ssp("none"), _application(), _cbhe_node(0), _cbhe_application(0)
186  {
187  }
188 
189  EID::EID(const Scheme scheme_type, const std::string &scheme, const std::string &ssp, const std::string &application)
190  : _scheme_type(scheme_type), _scheme(scheme), _ssp(ssp), _application(application), _cbhe_node(0), _cbhe_application(0)
191  {
192  if (scheme_type == SCHEME_CBHE) {
193  throw dtn::InvalidDataException("This constructor does not work for CBHE schemes");
194  }
195  }
196 
197  EID::EID(const std::string &scheme, const std::string &ssp)
198  : _scheme_type(SCHEME_EXTENDED), _scheme(), _ssp(ssp), _application(), _cbhe_node(0), _cbhe_application(0)
199  {
200  // resolve scheme
201  _scheme_type = resolveScheme(scheme);
202 
203  switch (_scheme_type) {
204  case SCHEME_CBHE:
205  // extract CBHE numbers
206  extractCBHE(ssp, _cbhe_node, _cbhe_application);
207  if (_cbhe_node == 0) {
208  _scheme_type = SCHEME_DTN;
209  _ssp = "none";
210  }
211  break;
212 
213  case SCHEME_DTN:
214  extractDTN(ssp, _ssp, _application);
215  break;
216 
217  default:
218  _scheme = scheme;
219  break;
220  }
221  }
222 
223  EID::EID(const std::string &orig_value)
224  : _scheme_type(SCHEME_DTN), _scheme(), _ssp("none"), _application(), _cbhe_node(0), _cbhe_application(0)
225  {
226  try {
227  if (orig_value.length() == 0) {
228  throw dtn::InvalidDataException("given EID is empty!");
229  }
230 
231  std::string value = orig_value;
233 
234  // search for the delimiter
235  const size_t delimiter = value.find_first_of(":");
236 
237  // jump to default eid if the format is wrong
238  if (delimiter == std::string::npos)
239  throw dtn::InvalidDataException("wrong EID format: " + value);
240 
241  // the scheme is everything before the delimiter
242  const std::string scheme = value.substr(0, delimiter);
243 
244  // the ssp is everything else
245  const size_t startofssp = delimiter + 1;
246  const std::string ssp = value.substr(startofssp, value.length() - delimiter + 1);
247 
248  // do syntax check
249  if (scheme.length() == 0) {
250  throw dtn::InvalidDataException("scheme is empty!");
251  }
252 
253  if (ssp.length() == 0) {
254  throw dtn::InvalidDataException("SSP is empty!");
255  }
256 
257  // resolve scheme
258  _scheme_type = resolveScheme(scheme);
259 
260  switch (_scheme_type) {
261  case SCHEME_CBHE:
262  // extract CBHE numbers
263  extractCBHE(ssp, _cbhe_node, _cbhe_application);
264  break;
265 
266  case SCHEME_DTN:
267  // extract DTN scheme node/application
268  extractDTN(ssp, _ssp, _application);
269  break;
270 
271  default:
272  _scheme = scheme;
273  _ssp = ssp;
274  break;
275  }
276  } catch (const std::exception&) {
277  _scheme_type = SCHEME_DTN;
278  _ssp = "none";
279  }
280  }
281 
282  EID::EID(const dtn::data::Number &node, const dtn::data::Number &application)
283  : _scheme_type(SCHEME_CBHE), _scheme(), _ssp(), _application(), _cbhe_node(node), _cbhe_application(application)
284  {
285  // set dtn:none if the node is zero
286  if (node == 0) {
287  _scheme_type = SCHEME_DTN;
288  _ssp = "none";
289  }
290  }
291 
293  {
294  }
295 
296  bool EID::operator==(const EID &other) const
297  {
298  if (_scheme_type != other._scheme_type) return false;
299 
300  switch (_scheme_type) {
301  case SCHEME_CBHE:
302  return (_cbhe_node == other._cbhe_node) && (_cbhe_application == other._cbhe_application);
303 
304  case SCHEME_DTN:
305  return (_ssp == other._ssp) && (_application == other._application);
306 
307  default:
308  return (_scheme == other._scheme) && (_ssp == other._ssp);
309  }
310  }
311 
312  bool EID::operator==(const std::string &other) const
313  {
314  return ((*this) == EID(other));
315  }
316 
317  bool EID::operator!=(const EID &other) const
318  {
319  return !((*this) == other);
320  }
321 
322  bool EID::sameHost(const std::string& other) const
323  {
324  return sameHost( EID(other) );
325  }
326 
327  bool EID::sameHost(const EID &other) const
328  {
329  if (_scheme_type != other._scheme_type) return false;
330 
331  switch (_scheme_type) {
332  case SCHEME_CBHE:
333  return _cbhe_node == other._cbhe_node;
334 
335  case SCHEME_DTN:
336  return _ssp == other._ssp;
337 
338  default:
339  return (_scheme == other._scheme) && (_ssp == other._ssp);
340  }
341  }
342 
343  bool EID::operator<(const EID &other) const
344  {
345  if (_scheme_type < other._scheme_type) return true;
346  if (_scheme_type != other._scheme_type) return false;
347 
348  switch (_scheme_type) {
349  case SCHEME_CBHE:
350  if (_cbhe_node < other._cbhe_node) return true;
351  if (_cbhe_node != other._cbhe_node) return false;
352 
353  return (_cbhe_application < other._cbhe_application);
354 
355  case SCHEME_DTN:
356  if (_ssp < other._ssp) return true;
357  if (_ssp != other._ssp) return false;
358 
359  return (_application < other._application);
360 
361  default:
362  if (_scheme < other._scheme) return true;
363  if (_scheme != other._scheme) return false;
364 
365  return (_ssp < other._ssp);
366  }
367  }
368 
369  bool EID::operator>(const EID &other) const
370  {
371  return other < (*this);
372  }
373 
374  std::string EID::getString() const
375  {
376  std::stringstream ss;
377 
378  switch (_scheme_type) {
379  case SCHEME_CBHE:
380  ss << getSchemeName(SCHEME_CBHE) << ":" << _cbhe_node.get<size_t>();
381 
382  if (_cbhe_application > 0) {
383  ss << "." << _cbhe_application.get<size_t>();
384  }
385  break;
386 
387  case SCHEME_DTN:
388  ss << getSchemeName(SCHEME_DTN) << ":" << _ssp;
389 
390  if (_application.length() > 0) {
391  ss << "/" << _application;
392  }
393  break;
394 
395  default:
396  ss << _scheme << ":" << _ssp;
397  break;
398  }
399 
400  return ss.str();
401  }
402 
403  void EID::setApplication(const Number &app) throw ()
404  {
405  switch (_scheme_type) {
406  case SCHEME_CBHE:
407  _cbhe_application = app;
408  break;
409 
410  case SCHEME_DTN:
411  _application = app.toString();
412  break;
413 
414  default:
415  // not defined
416  break;
417  }
418  }
419 
420  void EID::setApplication(const std::string &app) throw ()
421  {
422  switch (_scheme_type) {
423  case SCHEME_CBHE:
424  // get CBHE Number for the application string
425  _cbhe_application = EID::getApplicationNumber(app);
426  break;
427 
428  case SCHEME_DTN:
429  _application = app;
430  break;
431 
432  default:
433  // not defined
434  break;
435  }
436  }
437 
438  std::string EID::getApplication() const throw ()
439  {
440  switch (_scheme_type) {
441  case SCHEME_CBHE:
442  if (_cbhe_application > 0) {
443  return _cbhe_application.toString();
444  }
445  return "";
446 
447  case SCHEME_DTN:
448  return _application;
449 
450  default:
451  return _ssp;
452  }
453  }
454 
455  bool EID::isApplication(const dtn::data::Number &app) const throw ()
456  {
457  if (_scheme_type != SCHEME_CBHE) return false;
458  return (_cbhe_application == app);
459  }
460 
461  bool EID::isApplication(const std::string &app) const throw ()
462  {
463  switch (_scheme_type) {
464  case SCHEME_CBHE:
465  return (_cbhe_application == getApplicationNumber(app));
466 
467  case SCHEME_DTN:
468  return (_application == app);
469 
470  default:
471  return (app == _ssp);
472  }
473  }
474 
475  std::string EID::getHost() const throw ()
476  {
477  switch (_scheme_type) {
478  case SCHEME_CBHE:
479  return _cbhe_node.toString();
480  case SCHEME_DTN:
481  return _ssp;
482  default:
483  return _ssp;
484  }
485  }
486 
487  const std::string EID::getScheme() const
488  {
489  switch (_scheme_type) {
490  case SCHEME_CBHE:
491  return getSchemeName(SCHEME_CBHE);
492  case SCHEME_DTN:
493  return getSchemeName(SCHEME_DTN);
494  default:
495  return _scheme;
496  }
497  }
498 
499  const std::string EID::getSSP() const
500  {
501  switch (_scheme_type) {
502  case SCHEME_CBHE:
503  {
504  std::stringstream ss;
505  ss << _cbhe_node.get<size_t>();
506 
507  if (_cbhe_application > 0) {
508  ss << "." << _cbhe_application.get<size_t>();
509  }
510 
511  return ss.str();
512  }
513 
514  case SCHEME_DTN:
515  if (_application.length() > 0) {
516  std::stringstream ss;
517  ss << _ssp << "/" << _application;
518  return ss.str();
519  } else {
520  return _ssp;
521  }
522 
523  default:
524  return _ssp;
525  }
526  }
527 
528  EID EID::getNode() const throw ()
529  {
530  switch (_scheme_type) {
531  case SCHEME_CBHE:
532  return EID(_cbhe_node, 0);
533  case SCHEME_DTN:
534  return EID(_scheme_type, "", _ssp, "");
535  default:
536  return EID(_scheme_type, _scheme, _ssp, "");
537  }
538  }
539 
540  bool EID::hasApplication() const
541  {
542  switch (_scheme_type) {
543  case SCHEME_CBHE:
544  return (_cbhe_application > 0);
545  case SCHEME_DTN:
546  return _application != "";
547  default:
548  return true;
549  }
550  }
551 
552  bool EID::isCompressable() const
553  {
554  return ((_scheme_type == SCHEME_CBHE) || ((_scheme_type == SCHEME_DTN) && (_ssp == "none")));
555  }
556 
557  bool EID::isNone() const
558  {
559  return (_scheme_type == SCHEME_DTN) && (_ssp == "none");
560  }
561 
562  std::string EID::getDelimiter() const
563  {
564  if (_scheme_type == EID::SCHEME_CBHE) {
565  return ".";
566  } else {
567  return "/";
568  }
569  }
570 
572  {
573  if (isCompressable())
574  {
575  return make_pair(_cbhe_node, _cbhe_application);
576  }
577 
578  return make_pair(0, 0);
579  }
580  }
581 }