libtins  3.4
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
memory_helpers.h
1 /*
2  * Copyright (c) 2016, Matias Fontanini
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_MEMORY_HELPERS_H
31 #define TINS_MEMORY_HELPERS_H
32 
33 #include <stdint.h>
34 #include <cstring>
35 #include <algorithm>
36 #include <vector>
37 #include "exceptions.h"
38 #include "ip_address.h"
39 #include "ipv6_address.h"
40 #include "hw_address.h"
41 #include "endianness.h"
42 
43 namespace Tins {
44 
48 namespace Memory {
49 
50 inline void read_data(const uint8_t* buffer, uint8_t* output_buffer, size_t size) {
51  std::memcpy(output_buffer, buffer, size);
52 }
53 
54 template <typename T>
55 void read_value(const uint8_t* buffer, T& value) {
56  std::memcpy(&value, buffer, sizeof(value));
57 }
58 
59 inline void write_data(uint8_t* buffer, const uint8_t* ptr, size_t size) {
60  std::memcpy(buffer, ptr, size);
61 }
62 
63 template <typename T>
64 void write_value(uint8_t* buffer, const T& value) {
65  std::memcpy(buffer, &value, sizeof(value));
66 }
67 
68 class InputMemoryStream {
69 public:
70  InputMemoryStream(const uint8_t* buffer, size_t total_sz)
71  : buffer_(buffer), size_(total_sz) {
72  }
73 
74  InputMemoryStream(const std::vector<uint8_t>& data)
75  : buffer_(&data[0]), size_(data.size()) {
76  }
77 
78  void skip(size_t size) {
79  if (TINS_UNLIKELY(size > size_)) {
80  throw malformed_packet();
81  }
82  buffer_ += size;
83  size_ -= size;
84  }
85 
86  bool can_read(size_t byte_count) const {
87  return TINS_LIKELY(size_ >= byte_count);
88  }
89 
90  template <typename T>
91  T read() {
92  T output;
93  read(output);
94  return output;
95  }
96 
97  template <typename T>
98  T read_le() {
99  return Endian::le_to_host(read<T>());
100  }
101 
102  template <typename T>
103  T read_be() {
104  return Endian::be_to_host(read<T>());
105  }
106 
107  template <typename T>
108  void read(T& value) {
109  if (!can_read(sizeof(value))) {
110  throw malformed_packet();
111  }
112  read_value(buffer_, value);
113  skip(sizeof(value));
114  }
115 
116  void read(std::vector<uint8_t>& value, size_t count) {
117  if (!can_read(count)) {
118  throw malformed_packet();
119  }
120  value.assign(pointer(), pointer() + count);
121  skip(count);
122  }
123 
124  void read(IPv4Address& address) {
125  address = IPv4Address(read<uint32_t>());
126  }
127 
128  void read(IPv6Address& address) {
129  if (!can_read(IPv6Address::address_size)) {
130  throw malformed_packet();
131  }
132  address = pointer();
133  skip(IPv6Address::address_size);
134  }
135 
136  template <size_t n>
137  void read(HWAddress<n>& address) {
138  if (!can_read(HWAddress<n>::address_size)) {
139  throw malformed_packet();
140  }
141  address = pointer();
142  skip(HWAddress<n>::address_size);
143  }
144 
145  void read(void* output_buffer, size_t output_buffer_size) {
146  if (!can_read(output_buffer_size)) {
147  throw malformed_packet();
148  }
149  read_data(buffer_, (uint8_t*)output_buffer, output_buffer_size);
150  skip(output_buffer_size);
151  }
152 
153  const uint8_t* pointer() const {
154  return buffer_;
155  }
156 
157  size_t size() const {
158  return size_;
159  }
160 
161  void size(size_t new_size) {
162  size_ = new_size;
163  }
164 
165  operator bool() const {
166  return size_ > 0;
167  }
168 private:
169  const uint8_t* buffer_;
170  size_t size_;
171 };
172 
173 class OutputMemoryStream {
174 public:
175  OutputMemoryStream(uint8_t* buffer, size_t total_sz)
176  : buffer_(buffer), size_(total_sz) {
177  }
178 
179  OutputMemoryStream(std::vector<uint8_t>& buffer)
180  : buffer_(&buffer[0]), size_(buffer.size()) {
181  }
182 
183  void skip(size_t size) {
184  if (TINS_UNLIKELY(size > size_)) {
185  throw malformed_packet();
186  }
187  buffer_ += size;
188  size_ -= size;
189  }
190 
191  template <typename T>
192  void write(const T& value) {
193  if (TINS_UNLIKELY(size_ < sizeof(value))) {
194  throw serialization_error();
195  }
196  write_value(buffer_, value);
197  skip(sizeof(value));
198  }
199 
200  template <typename T>
201  void write_be(const T& value) {
202  write(Endian::host_to_be(value));
203  }
204 
205  template <typename T>
206  void write_le(const T& value) {
207  write(Endian::host_to_le(value));
208  }
209 
210  template <typename ForwardIterator>
211  void write(ForwardIterator start, ForwardIterator end) {
212  const size_t length = std::distance(start, end);
213  if (TINS_UNLIKELY(size_ < length)) {
214  throw serialization_error();
215  }
216  std::copy(start, end, buffer_);
217  skip(length);
218  }
219 
220  void write(const uint8_t* ptr, size_t length) {
221  write(ptr, ptr + length);
222  }
223 
224  void write(const IPv4Address& address) {
225  write(static_cast<uint32_t>(address));
226  }
227 
228  void write(const IPv6Address& address) {
229  write(address.begin(), address.end());
230  }
231 
232  template <size_t n>
233  void write(const HWAddress<n>& address) {
234  write(address.begin(), address.end());
235  }
236 
237  void fill(size_t size, uint8_t value) {
238  if (TINS_UNLIKELY(size_ < size)) {
239  throw serialization_error();
240  }
241  std::fill(buffer_, buffer_ + size, value);
242  skip(size);
243  }
244 
245  uint8_t* pointer() {
246  return buffer_;
247  }
248 
249  size_t size() const {
250  return size_;
251  }
252 private:
253  uint8_t* buffer_;
254  size_t size_;
255 };
256 
261 } // Memory
262 } // Tins
263 
264 #endif // TINS_MEMORY_HELPERS_H