IBR-DTNSuite  0.12
BundleID.cpp
Go to the documentation of this file.
1 /*
2  * BundleID.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/BundleID.h"
24 #include "ibrdtn/data/Number.h"
26 #include <string.h>
27 
28 // include code for platform-independent endianess conversion
29 #include "ibrdtn/data/Endianess.h"
30 
31 namespace dtn
32 {
33  namespace data
34  {
35  const unsigned int BundleID::RAW_LENGTH_MAX = 33 + 1024 + 1 + 1024;
36 
38  : source(), timestamp(0), sequencenumber(0), fragmentoffset(0), _fragment(false), _payloadlength(0)
39  {
40  }
41 
43  : source(id.source), timestamp(id.timestamp), sequencenumber(id.sequencenumber),
44  fragmentoffset(id.fragmentoffset), _fragment(id.isFragment()), _payloadlength(id.getPayloadLength())
45  {
46  }
47 
49  {
50  }
51 
53  {
54  source = id.source;
55  timestamp = id.timestamp;
56  sequencenumber = id.sequencenumber;
57  fragmentoffset = id.fragmentoffset;
58  setFragment(id.isFragment());
60  return (*this);
61  }
62 
63  bool BundleID::operator<(const BundleID& other) const
64  {
65  if (source < other.source) return true;
66  if (source != other.source) return false;
67 
68  if (timestamp < other.timestamp) return true;
69  if (timestamp != other.timestamp) return false;
70 
71  if (sequencenumber < other.sequencenumber) return true;
72  if (sequencenumber != other.sequencenumber) return false;
73 
74  if (other.isFragment())
75  {
76  if (!isFragment()) return true;
77  if (fragmentoffset < other.fragmentoffset) return true;
78  if (fragmentoffset != other.fragmentoffset) return false;
79 
80  return (getPayloadLength() < other.getPayloadLength());
81  }
82 
83  return false;
84  }
85 
86  bool BundleID::operator>(const BundleID& other) const
87  {
88  return !(((*this) < other) || ((*this) == other));
89  }
90 
91  bool BundleID::operator!=(const BundleID& other) const
92  {
93  return !((*this) == other);
94  }
95 
96  bool BundleID::operator==(const BundleID& other) const
97  {
98  if (other.timestamp != timestamp) return false;
99  if (other.sequencenumber != sequencenumber) return false;
100  if (other.source != source) return false;
101  if (other.isFragment() != isFragment()) return false;
102 
103  if (isFragment())
104  {
105  if (other.fragmentoffset != fragmentoffset) return false;
106  if (other.getPayloadLength() != getPayloadLength()) return false;
107  }
108 
109  return true;
110  }
111 
113  {
114  return _payloadlength;
115  }
116 
118  {
119  _payloadlength = value;
120  }
121 
122  bool BundleID::isFragment() const
123  {
124  return _fragment;
125  }
126 
127  void BundleID::setFragment(bool val)
128  {
129  _fragment = val;
130  }
131 
133  {
134  unsigned char data[RAW_LENGTH_MAX];
135  const size_t data_len = raw((unsigned char*)&data, RAW_LENGTH_MAX);
136  bf.insert((unsigned char*)&data, data_len);
137  }
138 
140  {
141  unsigned char data[RAW_LENGTH_MAX];
142  const size_t data_len = raw((unsigned char*)&data, RAW_LENGTH_MAX);
143  return bf.contains((unsigned char*)&data, data_len);
144  }
145 
146  size_t BundleID::raw(unsigned char *data, size_t len) const
147  {
148  uint64_t tmp = 0;
149 
150  // stop here if there is not enough space
151  if (len < 33) return 0;
152 
153  // add timestamp data
154  tmp = GUINT64_TO_BE(timestamp.get<uint64_t>());
155  ::memcpy(data, reinterpret_cast<unsigned char*>(&tmp), sizeof(tmp));
156  data += sizeof(tmp);
157 
158  // add sequencenumber
159  tmp = GUINT64_TO_BE(sequencenumber.get<uint64_t>());
160  ::memcpy(data, reinterpret_cast<unsigned char*>(&tmp), sizeof(tmp));
161  data += sizeof(tmp);
162 
163  // add fragment yes/no
164  (uint8_t&)(*data) = isFragment() ? 1 : 0;
165  data += sizeof(uint8_t);
166 
167  // add fragment offset
168  tmp = isFragment() ? GUINT64_TO_BE(fragmentoffset.get<uint64_t>()) : 0;
169  ::memcpy(data, reinterpret_cast<unsigned char*>(&tmp), sizeof(tmp));
170  data += sizeof(tmp);
171 
172  // add fragment length
173  tmp = isFragment() ? GUINT64_TO_BE(getPayloadLength()) : 0;
174  ::memcpy(data, reinterpret_cast<unsigned char*>(&tmp), sizeof(tmp));
175  data += sizeof(tmp);
176 
177  // get source endpoint string
178  const std::string s = source.getString();
179 
180  // copy source endpoint into data array
181  ::strncpy((char*)data, s.c_str(), len - 33);
182 
183  if ((len - 33) < s.length()) {
184  return len;
185  } else {
186  return 33 + s.length();
187  }
188  }
189 
190  std::string BundleID::toString() const
191  {
192  stringstream ss;
193  ss << "[" << timestamp.toString() << "." << sequencenumber.toString();
194 
195  if (isFragment())
196  {
197  ss << "." << fragmentoffset.toString();
198  ss << "." << getPayloadLength();
199  }
200 
201  ss << "] " << source.getString();
202 
203  return ss.str();
204  }
205 
206  std::ostream &operator<<(std::ostream &stream, const BundleID &obj)
207  {
209 
210  stream << obj.timestamp << obj.sequencenumber;
211 
212  if (obj.isFragment()) {
213  stream.put(1);
214  stream << obj.fragmentoffset;
215  stream << dtn::data::Number(obj.getPayloadLength());
216  } else {
217  stream.put(0);
218  }
219 
220  stream << source;
221 
222  return stream;
223  }
224 
225  std::istream &operator>>(std::istream &stream, BundleID &obj)
226  {
228 
229  stream >> obj.timestamp >> obj.sequencenumber;
230 
231  uint8_t frag = 0;
232  stream.get((char&)frag);
233 
234  if (frag == 1) {
235  stream >> obj.fragmentoffset;
236  dtn::data::Number tmp;
237  stream >> tmp;
238  obj.setPayloadLength(tmp.get<dtn::data::Length>());
239  obj.setFragment(true);
240  } else {
241  obj.setFragment(false);
242  }
243 
244  stream >> source;
245  obj.source = dtn::data::EID(source);
246 
247  return stream;
248  }
249  }
250 }