Botan  2.4.0
Crypto and TLS for C++11
secqueue.cpp
Go to the documentation of this file.
1 /*
2 * SecureQueue
3 * (C) 1999-2007 Jack Lloyd
4 * 2012 Markus Wanner
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/secqueue.h>
10 #include <algorithm>
11 
12 namespace Botan {
13 
14 /**
15 * A node in a SecureQueue
16 */
17 class SecureQueueNode final
18  {
19  public:
20  SecureQueueNode() : m_buffer(DEFAULT_BUFFERSIZE)
21  { m_next = nullptr; m_start = m_end = 0; }
22 
23  ~SecureQueueNode() { m_next = nullptr; m_start = m_end = 0; }
24 
25  size_t write(const uint8_t input[], size_t length)
26  {
27  size_t copied = std::min<size_t>(length, m_buffer.size() - m_end);
28  copy_mem(m_buffer.data() + m_end, input, copied);
29  m_end += copied;
30  return copied;
31  }
32 
33  size_t read(uint8_t output[], size_t length)
34  {
35  size_t copied = std::min(length, m_end - m_start);
36  copy_mem(output, m_buffer.data() + m_start, copied);
37  m_start += copied;
38  return copied;
39  }
40 
41  size_t peek(uint8_t output[], size_t length, size_t offset = 0)
42  {
43  const size_t left = m_end - m_start;
44  if(offset >= left) return 0;
45  size_t copied = std::min(length, left - offset);
46  copy_mem(output, m_buffer.data() + m_start + offset, copied);
47  return copied;
48  }
49 
50  size_t size() const { return (m_end - m_start); }
51  private:
52  friend class SecureQueue;
53  SecureQueueNode* m_next;
54  secure_vector<uint8_t> m_buffer;
55  size_t m_start, m_end;
56  };
57 
58 /*
59 * Create a SecureQueue
60 */
62  {
63  m_bytes_read = 0;
64  set_next(nullptr, 0);
65  m_head = m_tail = new SecureQueueNode;
66  }
67 
68 /*
69 * Copy a SecureQueue
70 */
73  {
74  m_bytes_read = 0;
75  set_next(nullptr, 0);
76 
77  m_head = m_tail = new SecureQueueNode;
78  SecureQueueNode* temp = input.m_head;
79  while(temp)
80  {
81  write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
82  temp = temp->m_next;
83  }
84  }
85 
86 /*
87 * Destroy this SecureQueue
88 */
89 void SecureQueue::destroy()
90  {
91  SecureQueueNode* temp = m_head;
92  while(temp)
93  {
94  SecureQueueNode* holder = temp->m_next;
95  delete temp;
96  temp = holder;
97  }
98  m_head = m_tail = nullptr;
99  }
100 
101 /*
102 * Copy a SecureQueue
103 */
105  {
106  if(this == &input)
107  return *this;
108 
109  destroy();
110  m_bytes_read = input.get_bytes_read();
111  m_head = m_tail = new SecureQueueNode;
112  SecureQueueNode* temp = input.m_head;
113  while(temp)
114  {
115  write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start);
116  temp = temp->m_next;
117  }
118  return (*this);
119  }
120 
121 /*
122 * Add some bytes to the queue
123 */
124 void SecureQueue::write(const uint8_t input[], size_t length)
125  {
126  if(!m_head)
127  m_head = m_tail = new SecureQueueNode;
128  while(length)
129  {
130  const size_t n = m_tail->write(input, length);
131  input += n;
132  length -= n;
133  if(length)
134  {
135  m_tail->m_next = new SecureQueueNode;
136  m_tail = m_tail->m_next;
137  }
138  }
139  }
140 
141 /*
142 * Read some bytes from the queue
143 */
144 size_t SecureQueue::read(uint8_t output[], size_t length)
145  {
146  size_t got = 0;
147  while(length && m_head)
148  {
149  const size_t n = m_head->read(output, length);
150  output += n;
151  got += n;
152  length -= n;
153  if(m_head->size() == 0)
154  {
155  SecureQueueNode* holder = m_head->m_next;
156  delete m_head;
157  m_head = holder;
158  }
159  }
160  m_bytes_read += got;
161  return got;
162  }
163 
164 /*
165 * Read data, but do not remove it from queue
166 */
167 size_t SecureQueue::peek(uint8_t output[], size_t length, size_t offset) const
168  {
169  SecureQueueNode* current = m_head;
170 
171  while(offset && current)
172  {
173  if(offset >= current->size())
174  {
175  offset -= current->size();
176  current = current->m_next;
177  }
178  else
179  break;
180  }
181 
182  size_t got = 0;
183  while(length && current)
184  {
185  const size_t n = current->peek(output, length, offset);
186  offset = 0;
187  output += n;
188  got += n;
189  length -= n;
190  current = current->m_next;
191  }
192  return got;
193  }
194 
195 /**
196 * Return how many bytes have been read so far.
197 */
199  {
200  return m_bytes_read;
201  }
202 
203 /*
204 * Return how many bytes the queue holds
205 */
206 size_t SecureQueue::size() const
207  {
208  SecureQueueNode* current = m_head;
209  size_t count = 0;
210 
211  while(current)
212  {
213  count += current->size();
214  current = current->m_next;
215  }
216  return count;
217  }
218 
219 /*
220 * Test if the queue has any data in it
221 */
223  {
224  return (size() == 0);
225  }
226 
227 bool SecureQueue::empty() const
228  {
229  return (size() == 0);
230  }
231 
232 }
size_t read(uint8_t[], size_t) override
Definition: secqueue.cpp:144
size_t size() const
Definition: secqueue.cpp:206
void set_next(Filter *f[], size_t n)
Definition: filter.h:162
SecureQueue & operator=(const SecureQueue &other)
Definition: secqueue.cpp:104
void write(const uint8_t[], size_t) override
Definition: secqueue.cpp:124
size_t peek(uint8_t[], size_t, size_t=0) const override
Definition: secqueue.cpp:167
size_t get_bytes_read() const override
Definition: secqueue.cpp:198
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:97
Definition: alg_id.cpp:13
bool empty() const
Definition: secqueue.cpp:227
bool end_of_data() const override
Definition: secqueue.cpp:222