Botan  1.11.10
pipe.cpp
Go to the documentation of this file.
1 /*
2 * Pipe
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
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)
24  { send(input, length); }
25 
26  std::string name() const { 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(pipe);
60  delete outputs;
61  }
62 
63 /*
64 * Initialize the Pipe
65 */
66 void Pipe::init()
67  {
68  outputs = new Output_Buffers;
69  pipe = nullptr;
70  default_read = 0;
71  inside_msg = false;
72  }
73 
74 /*
75 * Reset the Pipe
76 */
78  {
79  destruct(pipe);
80  pipe = nullptr;
81  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->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  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[0], input.size());
130  }
131 
132 void Pipe::process_msg(const std::vector<byte>& input)
133  {
134  process_msg(&input[0], 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(inside_msg)
161  throw Invalid_State("Pipe::start_msg: Message was already started");
162  if(pipe == nullptr)
163  pipe = new Null_Filter;
164  find_endpoints(pipe);
165  pipe->new_msg();
166  inside_msg = true;
167  }
168 
169 /*
170 * End the current message
171 */
173  {
174  if(!inside_msg)
175  throw Invalid_State("Pipe::end_msg: Message was already ended");
176  pipe->finish_msg();
177  clear_endpoints(pipe);
178  if(dynamic_cast<Null_Filter*>(pipe))
179  {
180  delete pipe;
181  pipe = nullptr;
182  }
183  inside_msg = false;
184 
185  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->next[j] && !dynamic_cast<SecureQueue*>(f->next[j]))
195  find_endpoints(f->next[j]);
196  else
197  {
198  SecureQueue* q = new SecureQueue;
199  f->next[j] = q;
200  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->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
213  f->next[j] = nullptr;
214  clear_endpoints(f->next[j]);
215  }
216  }
217 
218 /*
219 * Append a Filter to the Pipe
220 */
221 void Pipe::append(Filter* filter)
222  {
223  if(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->owned)
230  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
231 
232  filter->owned = true;
233 
234  if(!pipe) pipe = filter;
235  else pipe->attach(filter);
236  }
237 
238 /*
239 * Prepend a Filter to the Pipe
240 */
241 void Pipe::prepend(Filter* filter)
242  {
243  if(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->owned)
250  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
251 
252  filter->owned = true;
253 
254  if(pipe) filter->attach(pipe);
255  pipe = filter;
256  }
257 
258 /*
259 * Pop a Filter off the Pipe
260 */
261 void Pipe::pop()
262  {
263  if(inside_msg)
264  throw Invalid_State("Cannot pop off a Pipe while it is processing");
265 
266  if(!pipe)
267  return;
268 
269  if(pipe->total_ports() > 1)
270  throw Invalid_State("Cannot pop off a Filter with multiple ports");
271 
272  Filter* f = pipe;
273  size_t owns = f->owns();
274  pipe = pipe->next[0];
275  delete f;
276 
277  while(owns--)
278  {
279  f = pipe;
280  pipe = pipe->next[0];
281  delete f;
282  }
283  }
284 
285 /*
286 * Return the number of messages in this Pipe
287 */
289  {
290  return 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
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:35
size_t message_id
Definition: pipe.h:33
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
void reset()
Definition: pipe.cpp:77
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
Definition: pipe_rw.cpp:131
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:92
static const message_id LAST_MESSAGE
Definition: pipe.h:54
bool end_of_data() const
Definition: pipe.cpp:99
Pipe(Filter *=nullptr, Filter *=nullptr, Filter *=nullptr, Filter *=nullptr)
Definition: pipe.cpp:34
uint8_t byte
Definition: types.h:30
Definition: buf_comp.h:15
void add(class SecureQueue *)
Definition: out_buf.cpp:64
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
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:117
void prepend(Filter *filt)
Definition: pipe.cpp:241
Pipe::message_id message_count() const
Definition: out_buf.cpp:109