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