Imported Upstream version 0.3.2
[anytun.git] / src / buffer.cpp
1 /*
2  *  anytun
3  *
4  *  The secure anycast tunneling protocol (satp) defines a protocol used
5  *  for communication between any combination of unicast and anycast
6  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
7  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
8  *  ethernet, ip, arp ...). satp directly includes cryptography and
9  *  message authentication based on the methodes used by SRTP.  It is
10  *  intended to deliver a generic, scaleable and secure solution for
11  *  tunneling and relaying of packets of any protocol.
12  *
13  *
14  *  Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl, 
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
19  *  Anytun is free software: you can redistribute it and/or modify
20  *  it under the terms of the GNU General Public License as published by
21  *  the Free Software Foundation, either version 3 of the License, or
22  *  any later version.
23  *
24  *  Anytun is distributed in the hope that it will be useful,
25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  *  GNU General Public License for more details.
28  *
29  *  You should have received a copy of the GNU General Public License
30  *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.
31  */
32
33 #include <cstring>
34 #include <stdexcept>
35 #include <string>
36 #include <sstream>
37 #include <iostream>
38 #include <boost/archive/text_oarchive.hpp>
39 #include <boost/archive/text_iarchive.hpp>
40 #include "datatypes.h"
41 #include "buffer.h"
42
43 Buffer::Buffer(bool allow_realloc) : buf_(0), length_(0), real_length_(0), allow_realloc_(allow_realloc)
44 {  
45 }
46
47 Buffer::Buffer(u_int32_t length, bool allow_realloc) : length_(length), real_length_(length_ + Buffer::OVER_SIZE_), 
48                                                        allow_realloc_(allow_realloc)
49 {
50   buf_ = new u_int8_t[real_length_];
51   if(!buf_) {
52     length_ = 0;
53     real_length_ = 0;
54     throw std::bad_alloc();
55   }
56   std::memset(buf_, 0, real_length_);
57 }
58
59 Buffer::Buffer(u_int8_t* data, u_int32_t length, bool allow_realloc) : length_(length), real_length_(length + Buffer::OVER_SIZE_), 
60                                                                        allow_realloc_(allow_realloc)
61 {
62   if(!data) {
63     length_ = 0;
64     real_length_ = 0;
65     return;
66   }
67
68   buf_ = new u_int8_t[real_length_];
69   if(!buf_) {
70     length_ = 0;
71     real_length_ = 0;
72     throw std::bad_alloc();
73   }
74   std::memcpy(buf_, data, length_);
75 }
76
77 Buffer::Buffer(std::string hex_data, bool allow_realloc) : length_(static_cast<u_int32_t>(hex_data.size())/2), 
78                                                            real_length_(length_ + Buffer::OVER_SIZE_),
79                                                            allow_realloc_(allow_realloc)
80 {
81   buf_ = new u_int8_t[real_length_];
82   if(!buf_) {
83     length_ = 0;
84     real_length_ = 0;
85     throw std::bad_alloc();
86   }
87   
88   for(u_int32_t i=0; i<length_; ++i)
89   {
90     u_int32_t tmp;
91     std::istringstream ss(std::string(hex_data.c_str(), i*2, 2));
92     if(!(ss >> std::hex >> tmp)) tmp = 0;
93     buf_[i] = static_cast<u_int8_t>(tmp);
94   }
95 }
96
97 Buffer::~Buffer()
98 {
99   if(buf_)
100     delete[] buf_;
101 }
102
103 Buffer::Buffer(const Buffer &src) : length_(src.length_), real_length_(src.real_length_), allow_realloc_(src.allow_realloc_)
104 {
105   buf_ = new u_int8_t[real_length_];
106   if(!buf_) {
107     length_ = 0;
108     real_length_ = 0;
109     throw std::bad_alloc();
110   }
111   std::memcpy(buf_, src.buf_, length_);
112 }
113
114 void Buffer::operator=(const Buffer &src)
115 {
116   if(buf_)
117     delete[] buf_;
118  
119   length_ = src.length_;
120   real_length_ = src.real_length_; 
121   allow_realloc_ = src.allow_realloc_;
122  
123   buf_ = new u_int8_t[real_length_];
124   if(!buf_) {
125     length_ = 0;
126     real_length_ = 0;
127     throw std::bad_alloc();
128   }
129   std::memcpy(buf_, src.buf_, length_);
130 }
131
132 bool Buffer::operator==(const Buffer &cmp) const
133 {
134   if(length_ != cmp.length_)
135     return false;
136
137   if(!std::memcmp(buf_, cmp.buf_, length_))
138     return true;
139
140   return false;
141 }
142
143 Buffer Buffer::operator^(const Buffer &xor_by) const
144 {
145   u_int32_t res_length = (xor_by.length_ > length_) ? xor_by.length_ : length_;
146   u_int32_t min_length = (xor_by.length_ < length_) ? xor_by.length_ : length_;
147   Buffer res(res_length);
148
149   for( u_int32_t index = 0; index < min_length; index++ )
150     res[index] = buf_[index] ^ xor_by[index];
151   
152   return res;
153 }
154
155 u_int32_t Buffer::getLength() const
156 {
157   return length_;
158 }
159
160 void Buffer::setLength(u_int32_t new_length)
161 {
162   if(new_length == length_)
163     return;
164
165   if(new_length > real_length_)
166   {
167     if(!allow_realloc_)
168       throw std::out_of_range("buffer::setLength() - reallocation not allowed for this Buffer");
169
170     u_int8_t* old_buf = buf_;
171     u_int32_t old_length = length_;
172
173     length_ = new_length;
174     real_length_ = length_ + Buffer::OVER_SIZE_;
175     
176     buf_ = new u_int8_t[real_length_];
177     if(!buf_) {
178       length_ = 0;
179       real_length_ = 0;
180       if(old_buf)
181         delete[] old_buf;
182       
183       throw std::bad_alloc();
184     }
185     std::memcpy(buf_, old_buf, old_length);
186
187     if(old_buf)
188       delete[] old_buf;
189
190     old_buf = &buf_[old_length];
191     std::memset(old_buf, 0, real_length_ - old_length);
192   }
193   else
194     length_ = new_length;
195
196   reinit();
197 }  
198
199
200 u_int8_t* Buffer::getBuf()
201 {
202   return buf_;
203 }
204
205 u_int8_t& Buffer::operator[](u_int32_t index)
206 {
207   if(index >= length_)
208     throw std::out_of_range("buffer::operator[]");
209
210   return buf_[index];
211 }
212
213 u_int8_t Buffer::operator[](u_int32_t index) const
214 {
215   if(index >= length_)
216     throw std::out_of_range("buffer::operator[] const");
217
218   return buf_[index];
219 }
220
221 Buffer::operator u_int8_t*()
222 {
223   return buf_;
224 }
225
226 std::string Buffer::getHexDump() const
227 {
228   std::stringstream ss;
229   ss << "Length=" << length_ << std::endl << std::hex << std::uppercase;
230   for( u_int32_t index = 0; index < length_; index++ )
231   {
232     ss << std::setw(2) << std::setfill('0') << u_int32_t(buf_[index]) << " ";
233     if(!((index+1) % 16)) {
234       ss << std::endl;
235       continue;
236     }
237     if(!((index+1) % 8))
238       ss << " ";
239   }
240   return ss.str();
241 }
242
243 std::string Buffer::getHexDumpOneLine() const
244 {
245   std::stringstream ss;
246   ss << length_ << " Bytes,'" << std::hex << std::uppercase;
247   for( u_int32_t index = 0; index < length_; index++ )
248   {
249     ss << std::setw(2) << std::setfill('0') << u_int32_t(buf_[index]);
250   }
251   ss << "'";
252   return ss.str();
253 }
254
255 bool Buffer::isReallocAllowed() const
256 {
257   return allow_realloc_;
258 }