IBR-DTN  1.0.0
DiscoveryBeacon.cpp
Go to the documentation of this file.
1 /*
2  * DiscoveryBeacon.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 "config.h"
23 #include "net/DiscoveryBeacon.h"
24 #include <ibrdtn/data/Exceptions.h>
25 #include <ibrdtn/data/Number.h>
26 #include <ibrcommon/Logger.h>
27 #include <typeinfo>
28 #include <iostream>
29 #include <vector>
30 
31 #ifdef __WIN32__
32 #include <winsock2.h>
33 #else
34 #include <netinet/in.h>
35 #endif
36 
37 namespace dtn
38 {
39  namespace net
40  {
42  : _version(version), _flags(BEACON_NO_FLAGS), _canonical_eid(eid), _sn(0), _period(1)
43  {
44  }
45 
47  {
48  }
49 
51  {
52  switch (_version)
53  {
54  case DISCO_VERSION_00:
55  return (_flags & DiscoveryBeacon::BEACON_SHORT);
56 
57  case DISCO_VERSION_01:
58  return !(_flags & DiscoveryBeacon::BEACON_CONTAINS_EID);
59  };
60 
61  return false;
62  }
63 
65  {
66  _canonical_eid = eid;
67  }
68 
70  {
71  return _canonical_eid;
72  }
73 
75  {
76  return _services;
77  }
78 
80  {
81  return _services;
82  }
83 
85  {
86  _services.clear();
87  }
88 
89  const DiscoveryService& DiscoveryBeacon::getService(const std::string &name) const
90  {
91  for (service_list::const_iterator iter = _services.begin(); iter != _services.end(); ++iter)
92  {
93  if ((*iter).getName() == name)
94  {
95  return (*iter);
96  }
97  }
98 
99  throw dtn::MissingObjectException("No service found with tag " + name);
100  }
101 
103  {
104  for (service_list::iterator iter = _services.begin(); iter != _services.end(); ++iter)
105  {
106  if ((*iter).getName() == name)
107  {
108  return (*iter);
109  }
110  }
111 
112  throw dtn::MissingObjectException("No service found with tag " + name);
113  }
114 
116  {
117  _services.push_back(service);
118  }
119 
120  void DiscoveryBeacon::setSequencenumber(uint16_t sequence)
121  {
122  _sn = sequence;
123  }
124 
126  {
127  _period = period;
128  }
129 
131  {
132  return _period;
133  }
134 
136  {
137  return _period > 1;
138  }
139 
140  std::ostream &operator<<(std::ostream &stream, const DiscoveryBeacon &announcement)
141  {
142  const dtn::net::DiscoveryBeacon::service_list &services = announcement._services;
143 
144  switch (announcement._version)
145  {
147  {
148  if (services.empty())
149  {
150  const unsigned char flags = DiscoveryBeacon::BEACON_SHORT | announcement._flags;
151  stream << (unsigned char)DiscoveryBeacon::DISCO_VERSION_00 << flags;
152  return stream;
153  }
154 
155  const dtn::data::BundleString eid(announcement._canonical_eid.getString());
156  dtn::data::Number beacon_len;
157 
158  // determine the beacon length
159  beacon_len += eid.getLength();
160 
161  // add service block length
162  for (dtn::net::DiscoveryBeacon::service_list::const_iterator iter = services.begin(); iter != services.end(); ++iter)
163  {
164  beacon_len += (*iter).getLength();
165  }
166 
167  stream << (unsigned char)DiscoveryBeacon::DISCO_VERSION_00 << announcement._flags << beacon_len << eid;
168 
169  for (dtn::net::DiscoveryBeacon::service_list::const_iterator iter = services.begin(); iter != services.end(); ++iter)
170  {
171  stream << (*iter);
172  }
173 
174  break;
175  }
176 
178  {
179  unsigned char flags = 0;
180 
181  stream << (unsigned char)DiscoveryBeacon::DISCO_VERSION_01;
182 
183  if (announcement._canonical_eid != dtn::data::EID())
184  {
185  flags |= DiscoveryBeacon::BEACON_CONTAINS_EID;
186  }
187 
188  if (!services.empty())
189  {
190  flags |= DiscoveryBeacon::BEACON_SERVICE_BLOCK;
191  }
192 
193  if ( announcement._period > 1 )
194  {
195  flags |= DiscoveryBeacon::BEACON_CONTAINS_PERIOD;
196  }
197 
198  stream << flags;
199 
200  // sequencenumber
201  const uint16_t sn = htons(announcement._sn);
202  stream.write( (const char*)&sn, 2 );
203 
204  if ( flags & DiscoveryBeacon::BEACON_CONTAINS_EID )
205  {
206  const dtn::data::BundleString eid(announcement._canonical_eid.getString());
207  stream << eid;
208  }
209 
210  if ( flags & DiscoveryBeacon::BEACON_SERVICE_BLOCK )
211  {
212  stream << dtn::data::Number(services.size());
213 
214  for (dtn::net::DiscoveryBeacon::service_list::const_iterator iter = services.begin(); iter != services.end(); ++iter)
215  {
216  stream << (*iter);
217  }
218  }
219 
220  // not standard conform in version 01!
221  if ( flags & DiscoveryBeacon::BEACON_CONTAINS_PERIOD )
222  {
223  // append beacon period
224  stream << announcement._period;
225  }
226 
227  break;
228  }
229 
231  {
232  uint8_t cl_type = 1;
233  char zero = '\0';
234  uint8_t interval = 10;
235  // uint32_t inet_addr;
236  uint16_t inet_port = htons(4556);
237  std::string eid = announcement._canonical_eid.getString();
238  uint16_t eid_len = htons((uint16_t)eid.length());
239  unsigned int add_zeros = (4 - (eid.length() % 4)) % 4;
240  uint16_t length = htons(static_cast<uint16_t>(12 + eid.length() + add_zeros));
241 
242 
243  stream << (unsigned char)cl_type;
244  stream.write((char*)&interval, 1);
245  stream.write((char*)&length, 2);
246 
247 // std::list<dtn::daemon::Configuration::NetConfig> interfaces = dtn::daemon::Configuration::getInstance().getInterfaces();
248 // dtn::daemon::Configuration::NetConfig &i = interfaces.front();
249 
250 // struct sockaddr_in sock_address;
251 //
252 // // set the local interface address
253 // i.interface.getAddress(&sock_address.sin_addr);
254 //
255 // stream.write((char*)&sock_address.sin_addr, 4);
256  stream.write(&zero, 1);
257  stream.write(&zero, 1);
258  stream.write(&zero, 1);
259  stream.write(&zero, 1);
260 
261  stream.write((char*)&inet_port, 2);
262  stream.write((char*)&eid_len, 2);
263  stream << eid;
264 
265  for (unsigned int i = 0; i < add_zeros; ++i)
266  {
267  stream.write((char*)&zero, 1);
268  }
269 
270  break;
271  }
272  }
273 
274  return stream;
275  }
276 
277  std::istream &operator>>(std::istream &stream, DiscoveryBeacon &announcement)
278  {
279  unsigned char version = 0;
280 
281  // do we running DTN2 compatibility mode?
282  if (announcement._version == DiscoveryBeacon::DTND_IPDISCOVERY)
283  {
284  // set version to IPDiscovery (DTN2)
286  }
287  else
288  {
289  // read IPND version of the frame
290  version = (unsigned char)stream.get();
291  }
292 
293  switch (version)
294  {
296  {
297  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 60) << "beacon version 1 received" << IBRCOMMON_LOGGER_ENDL;
298 
299  dtn::data::Number beacon_len;
300  dtn::data::Number eid_len;
301 
302  stream.get((char&)announcement._flags);
303 
304  // catch a short beacon
305  if (DiscoveryBeacon::BEACON_SHORT == announcement._flags)
306  {
307  announcement._canonical_eid = dtn::data::EID();
308  return stream;
309  }
310 
311  stream >> beacon_len;
312  int remain = beacon_len.get<int>();
313 
315  stream >> eid;
316  remain -= static_cast<int>(eid.getLength());
317 
318  announcement._canonical_eid = dtn::data::EID((const std::string&)eid);
319 
320  // get the services
321  dtn::net::DiscoveryBeacon::service_list &services = announcement._services;
322 
323  // clear the services
324  services.clear();
325 
326  while (remain > 0)
327  {
328  // decode the service blocks
329  DiscoveryService service;
330  stream >> service;
331  services.push_back(service);
332  remain -= static_cast<int>(service.getLength());
333  }
334  break;
335  }
336 
338  {
339  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 60) << "beacon version 2 received" << IBRCOMMON_LOGGER_ENDL;
340 
341  stream.get((char&)announcement._flags);
342 
343  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 85) << "beacon flags: " << hex << (int)announcement._flags << IBRCOMMON_LOGGER_ENDL;
344 
345  uint16_t sn = 0;
346  stream.read((char*)&sn, 2);
347 
348  // convert from network byte order
349  uint16_t sequencenumber = ntohs(sn);
350 
351  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 85) << "beacon sequence number: " << sequencenumber << IBRCOMMON_LOGGER_ENDL;
352 
353  if (announcement._flags & DiscoveryBeacon::BEACON_CONTAINS_EID)
354  {
356  stream >> eid;
357 
358  announcement._canonical_eid = dtn::data::EID((const std::string&)eid);
359 
360  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 85) << "beacon eid: " << (std::string)eid << IBRCOMMON_LOGGER_ENDL;
361  }
362 
363  if (announcement._flags & DiscoveryBeacon::BEACON_SERVICE_BLOCK)
364  {
365  // get the services
366  dtn::net::DiscoveryBeacon::service_list &services = announcement._services;
367 
368  // read the number of services
369  dtn::data::Number num_services;
370  stream >> num_services;
371 
372  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 85) << "beacon services (" << num_services.toString() << "): " << IBRCOMMON_LOGGER_ENDL;
373 
374  // clear the services
375  services.clear();
376 
377  for (unsigned int i = 0; num_services > i; ++i)
378  {
379  // decode the service blocks
380  DiscoveryService service;
381  stream >> service;
382  services.push_back(service);
383 
384  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 85) << "\t " << service.getName() << " [" << service.getParameters() << "]" << IBRCOMMON_LOGGER_ENDL;
385  }
386  }
387 
388  if (announcement._flags & DiscoveryBeacon::BEACON_BLOOMFILTER)
389  {
390  // read the bloom-filter
391  stream >> announcement._bloomfilter;
392  }
393 
394  // not standard conform in version 01!
395  if (announcement._flags & DiscoveryBeacon::BEACON_CONTAINS_PERIOD)
396  {
397  // read appended beacon period
398  stream >> announcement._period;
399  }
400 
401  break;
402  }
403 
405  {
406  uint8_t cl_type;
407  uint8_t interval;
408  uint16_t length;
409  uint32_t inet_addr;
410  uint16_t inet_port;
411  uint16_t eid_len;
412 
413  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 60) << "beacon IPDiscovery (DTN2) frame received" << IBRCOMMON_LOGGER_ENDL;
414 
415  stream.read((char*)&cl_type, 1);
416  stream.read((char*)&interval, 1);
417  stream.read((char*)&length, 2);
418  stream.read((char*)&inet_addr, 4);
419  stream.read((char*)&inet_port, 2);
420  stream.read((char*)&eid_len, 2);
421 
422  std::vector<char> eid(eid_len);
423  stream.read(&eid[0], eid.size());
424 
425  announcement._version = DiscoveryBeacon::DTND_IPDISCOVERY;
426  announcement._canonical_eid = dtn::data::EID(std::string(eid.begin(), eid.end()));
427 
428  break;
429  }
430 
431  default:
432  IBRCOMMON_LOGGER_DEBUG_TAG("DiscoveryBeacon", 60) << "unknown beacon received" << IBRCOMMON_LOGGER_ENDL;
433 
434  // Error, throw Exception!
435  throw InvalidProtocolException("The received data does not match the discovery protocol.");
436 
437  break;
438  }
439 
440  return stream;
441  }
442 
443  std::string DiscoveryBeacon::toString() const
444  {
445  stringstream ss;
446  ss << "ANNOUNCE: " << _canonical_eid.getString();
447  return ss.str();
448  }
449  }
450 }
const DiscoveryService & getService(const std::string &name) const
service_list & getServices()
std::list< DiscoveryService > service_list
std::ostream & operator<<(std::ostream &stream, const DiscoveryBeacon &announcement)
const std::string & getName() const
void setEID(const dtn::data::EID &eid)
size_t getLength() const
Definition: SDNV.h:99
const dtn::data::EID & getEID() const
std::string toString() const
Definition: SDNV.h:414
T get() const
Definition: SDNV.h:113
const dtn::data::Number & getPeriod() const
void setPeriod(const dtn::data::Number &period)
std::string toString() const
std::string getString() const
Definition: EID.cpp:374
dtn::data::SDNV< Size > Number
Definition: Number.h:38
DiscoveryBeacon(const Protocol version=DISCO_VERSION_00, const dtn::data::EID &eid=dtn::data::EID())
std::istream & operator>>(std::istream &stream, DiscoveryBeacon &announcement)
void addService(const DiscoveryService &service)
void setSequencenumber(uint16_t sequence)