Botan  1.11.26
pipe.cpp
Go to the documentation of this file.
1 /*
2 * Pipe
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/pipe.h>
9 #include <botan/internal/out_buf.h>
10 #include <botan/secqueue.h>
11 #include <botan/parsing.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 /*
18 * A Filter that does nothing
19 */
20 class Null_Filter : public Filter
21  {
22  public:
23  void write(const byte input[], size_t length) override
24  { send(input, length); }
25 
26  std::string name() const override { return "Null"; }
27  };
28 
29 }
30 
31 /*
32 * Pipe Constructor
33 */
34 Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
35  {
36  init();
37  append(f1);
38  append(f2);
39  append(f3);
40  append(f4);
41  }
42 
43 /*
44 * Pipe Constructor
45 */
46 Pipe::Pipe(std::initializer_list<Filter*> args)
47  {
48  init();
49 
50  for(auto i = args.begin(); i != args.end(); ++i)
51  append(*i);
52  }
53 
54 /*
55 * Pipe Destructor
56 */
58  {
59  destruct(m_pipe);
60  delete m_outputs;
61  }
62 
63 /*
64 * Initialize the Pipe
65 */
66 void Pipe::init()
67  {
68  m_outputs = new Output_Buffers;
69  m_pipe = nullptr;
70  m_default_read = 0;
71  m_inside_msg = false;
72  }
73 
74 /*
75 * Reset the Pipe
76 */
78  {
79  destruct(m_pipe);
80  m_pipe = nullptr;
81  m_inside_msg = false;
82  }
83 
84 /*
85 * Destroy the Pipe
86 */
87 void Pipe::destruct(Filter* to_kill)
88  {
89  if(!to_kill || dynamic_cast<SecureQueue*>(to_kill))
90  return;
91  for(size_t j = 0; j != to_kill->total_ports(); ++j)
92  destruct(to_kill->m_next[j]);
93  delete to_kill;
94  }
95 
96 /*
97 * Test if the Pipe has any data in it
98 */
99 bool Pipe::end_of_data() const
100  {
101  return (remaining() == 0);
102  }
103 
104 /*
105 * Set the default read message
106 */
108  {
109  if(msg >= message_count())
110  throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
111  m_default_read = msg;
112  }
113 
114 /*
115 * Process a full message at once
116 */
117 void Pipe::process_msg(const byte input[], size_t length)
118  {
119  start_msg();
120  write(input, length);
121  end_msg();
122  }
123 
124 /*
125 * Process a full message at once
126 */
128  {
129  process_msg(input.data(), input.size());
130  }
131 
132 void Pipe::process_msg(const std::vector<byte>& input)
133  {
134  process_msg(input.data(), input.size());
135  }
136 
137 /*
138 * Process a full message at once
139 */
140 void Pipe::process_msg(const std::string& input)
141  {
142  process_msg(reinterpret_cast<const byte*>(input.data()), input.length());
143  }
144 
145 /*
146 * Process a full message at once
147 */
149  {
150  start_msg();
151  write(input);
152  end_msg();
153  }
154 
155 /*
156 * Start a new message
157 */
159  {
160  if(m_inside_msg)
161  throw Invalid_State("Pipe::start_msg: Message was already started");
162  if(m_pipe == nullptr)
163  m_pipe = new Null_Filter;
164  find_endpoints(m_pipe);
165  m_pipe->new_msg();
166  m_inside_msg = true;
167  }
168 
169 /*
170 * End the current message
171 */
173  {
174  if(!m_inside_msg)
175  throw Invalid_State("Pipe::end_msg: Message was already ended");
176  m_pipe->finish_msg();
177  clear_endpoints(m_pipe);
178  if(dynamic_cast<Null_Filter*>(m_pipe))
179  {
180  delete m_pipe;
181  m_pipe = nullptr;
182  }
183  m_inside_msg = false;
184 
185  m_outputs->retire();
186  }
187 
188 /*
189 * Find the endpoints of the Pipe
190 */
191 void Pipe::find_endpoints(Filter* f)
192  {
193  for(size_t j = 0; j != f->total_ports(); ++j)
194  if(f->m_next[j] && !dynamic_cast<SecureQueue*>(f->m_next[j]))
195  find_endpoints(f->m_next[j]);
196  else
197  {
198  SecureQueue* q = new SecureQueue;
199  f->m_next[j] = q;
200  m_outputs->add(q);
201  }
202  }
203 
204 /*
205 * Remove the SecureQueues attached to the Filter
206 */
207 void Pipe::clear_endpoints(Filter* f)
208  {
209  if(!f) return;
210  for(size_t j = 0; j != f->total_ports(); ++j)
211  {
212  if(f->m_next[j] && dynamic_cast<SecureQueue*>(f->m_next[j]))
213  f->m_next[j] = nullptr;
214  clear_endpoints(f->m_next[j]);
215  }
216  }
217 
218 /*
219 * Append a Filter to the Pipe
220 */
221 void Pipe::append(Filter* filter)
222  {
223  if(m_inside_msg)
224  throw Invalid_State("Cannot append to a Pipe while it is processing");
225  if(!filter)
226  return;
227  if(dynamic_cast<SecureQueue*>(filter))
228  throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
229  if(filter->m_owned)
230  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
231 
232  filter->m_owned = true;
233 
234  if(!m_pipe) m_pipe = filter;
235  else m_pipe->attach(filter);
236  }
237 
238 /*
239 * Prepend a Filter to the Pipe
240 */
241 void Pipe::prepend(Filter* filter)
242  {
243  if(m_inside_msg)
244  throw Invalid_State("Cannot prepend to a Pipe while it is processing");
245  if(!filter)
246  return;
247  if(dynamic_cast<SecureQueue*>(filter))
248  throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
249  if(filter->m_owned)
250  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
251 
252  filter->m_owned = true;
253 
254  if(m_pipe) filter->attach(m_pipe);
255  m_pipe = filter;
256  }
257 
258 /*
259 * Pop a Filter off the Pipe
260 */
261 void Pipe::pop()
262  {
263  if(m_inside_msg)
264  throw Invalid_State("Cannot pop off a Pipe while it is processing");
265 
266  if(!m_pipe)
267  return;
268 
269  if(m_pipe->total_ports() > 1)
270  throw Invalid_State("Cannot pop off a Filter with multiple ports");
271 
272  Filter* f = m_pipe;
273  size_t owns = f->owns();
274  m_pipe = m_pipe->m_next[0];
275  delete f;
276 
277  while(owns--)
278  {
279  f = m_pipe;
280  m_pipe = m_pipe->m_next[0];
281  delete f;
282  }
283  }
284 
285 /*
286 * Return the number of messages in this Pipe
287 */
289  {
290  return m_outputs->message_count();
291  }
292 
293 /*
294 * Static Member Variables
295 */
297  static_cast<Pipe::message_id>(-2);
298 
300  static_cast<Pipe::message_id>(-1);
301 
302 }
void start_msg()
Definition: pipe.cpp:158
void append(Filter *filt)
Definition: pipe.cpp:221
size_t message_id
Definition: pipe.h:33
void reset()
Definition: pipe.cpp:77
static const message_id DEFAULT_MESSAGE
Definition: pipe.h:59
void end_msg()
Definition: pipe.cpp:172
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:96
static const message_id LAST_MESSAGE
Definition: pipe.h:54
Pipe(Filter *=nullptr, Filter *=nullptr, Filter *=nullptr, Filter *=nullptr)
Definition: pipe.cpp:34
Definition: alg_id.cpp:13
void pop()
Definition: pipe.cpp:261
void set_default_msg(message_id msg)
Definition: pipe.cpp:107
message_id message_count() const
Definition: pipe.cpp:288
bool end_of_data() const override
Definition: pipe.cpp:99
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:117
void prepend(Filter *filt)
Definition: pipe.cpp:241
std::uint8_t byte
Definition: types.h:31