Botan  1.10.9
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(Filter* filter_array[], size_t count)
47  {
48  init();
49  for(size_t j = 0; j != count; ++j)
50  append(filter_array[j]);
51  }
52 
53 /*
54 * Pipe Destructor
55 */
57  {
58  destruct(pipe);
59  delete outputs;
60  }
61 
62 /*
63 * Initialize the Pipe
64 */
65 void Pipe::init()
66  {
67  outputs = new Output_Buffers;
68  pipe = 0;
69  default_read = 0;
70  inside_msg = false;
71  }
72 
73 /*
74 * Reset the Pipe
75 */
77  {
78  destruct(pipe);
79  pipe = 0;
80  inside_msg = false;
81  }
82 
83 /*
84 * Destroy the Pipe
85 */
86 void Pipe::destruct(Filter* to_kill)
87  {
88  if(!to_kill || dynamic_cast<SecureQueue*>(to_kill))
89  return;
90  for(size_t j = 0; j != to_kill->total_ports(); ++j)
91  destruct(to_kill->next[j]);
92  delete to_kill;
93  }
94 
95 /*
96 * Test if the Pipe has any data in it
97 */
98 bool Pipe::end_of_data() const
99  {
100  return (remaining() == 0);
101  }
102 
103 /*
104 * Set the default read message
105 */
107  {
108  if(msg >= message_count())
109  throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
110  default_read = msg;
111  }
112 
113 /*
114 * Process a full message at once
115 */
116 void Pipe::process_msg(const byte input[], size_t length)
117  {
118  start_msg();
119  write(input, length);
120  end_msg();
121  }
122 
123 /*
124 * Process a full message at once
125 */
127  {
128  process_msg(&input[0], input.size());
129  }
130 
131 /*
132 * Process a full message at once
133 */
134 void Pipe::process_msg(const std::string& input)
135  {
136  process_msg(reinterpret_cast<const byte*>(input.data()), input.length());
137  }
138 
139 /*
140 * Process a full message at once
141 */
143  {
144  start_msg();
145  write(input);
146  end_msg();
147  }
148 
149 /*
150 * Start a new message
151 */
153  {
154  if(inside_msg)
155  throw Invalid_State("Pipe::start_msg: Message was already started");
156  if(pipe == 0)
157  pipe = new Null_Filter;
158  find_endpoints(pipe);
159  pipe->new_msg();
160  inside_msg = true;
161  }
162 
163 /*
164 * End the current message
165 */
167  {
168  if(!inside_msg)
169  throw Invalid_State("Pipe::end_msg: Message was already ended");
170  pipe->finish_msg();
171  clear_endpoints(pipe);
172  if(dynamic_cast<Null_Filter*>(pipe))
173  {
174  delete pipe;
175  pipe = 0;
176  }
177  inside_msg = false;
178 
179  outputs->retire();
180  }
181 
182 /*
183 * Find the endpoints of the Pipe
184 */
185 void Pipe::find_endpoints(Filter* f)
186  {
187  for(size_t j = 0; j != f->total_ports(); ++j)
188  if(f->next[j] && !dynamic_cast<SecureQueue*>(f->next[j]))
189  find_endpoints(f->next[j]);
190  else
191  {
192  SecureQueue* q = new SecureQueue;
193  f->next[j] = q;
194  outputs->add(q);
195  }
196  }
197 
198 /*
199 * Remove the SecureQueues attached to the Filter
200 */
201 void Pipe::clear_endpoints(Filter* f)
202  {
203  if(!f) return;
204  for(size_t j = 0; j != f->total_ports(); ++j)
205  {
206  if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
207  f->next[j] = 0;
208  clear_endpoints(f->next[j]);
209  }
210  }
211 
212 /*
213 * Append a Filter to the Pipe
214 */
215 void Pipe::append(Filter* filter)
216  {
217  if(inside_msg)
218  throw Invalid_State("Cannot append to a Pipe while it is processing");
219  if(!filter)
220  return;
221  if(dynamic_cast<SecureQueue*>(filter))
222  throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
223  if(filter->owned)
224  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
225 
226  filter->owned = true;
227 
228  if(!pipe) pipe = filter;
229  else pipe->attach(filter);
230  }
231 
232 /*
233 * Prepend a Filter to the Pipe
234 */
235 void Pipe::prepend(Filter* filter)
236  {
237  if(inside_msg)
238  throw Invalid_State("Cannot prepend to a Pipe while it is processing");
239  if(!filter)
240  return;
241  if(dynamic_cast<SecureQueue*>(filter))
242  throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
243  if(filter->owned)
244  throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
245 
246  filter->owned = true;
247 
248  if(pipe) filter->attach(pipe);
249  pipe = filter;
250  }
251 
252 /*
253 * Pop a Filter off the Pipe
254 */
255 void Pipe::pop()
256  {
257  if(inside_msg)
258  throw Invalid_State("Cannot pop off a Pipe while it is processing");
259 
260  if(!pipe)
261  return;
262 
263  if(pipe->total_ports() > 1)
264  throw Invalid_State("Cannot pop off a Filter with multiple ports");
265 
266  Filter* f = pipe;
267  size_t owns = f->owns();
268  pipe = pipe->next[0];
269  delete f;
270 
271  while(owns--)
272  {
273  f = pipe;
274  pipe = pipe->next[0];
275  delete f;
276  }
277  }
278 
279 /*
280 * Return the number of messages in this Pipe
281 */
283  {
284  return outputs->message_count();
285  }
286 
287 /*
288 * Static Member Variables
289 */
291  static_cast<Pipe::message_id>(-2);
292 
294  static_cast<Pipe::message_id>(-1);
295 
296 }
void start_msg()
Definition: pipe.cpp:152
void append(Filter *filt)
Definition: pipe.cpp:215
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
size_t message_id
Definition: pipe.h:31
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
void reset()
Definition: pipe.cpp:76
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
Definition: pipe_rw.cpp:138
static const message_id DEFAULT_MESSAGE
Definition: pipe.h:57
unsigned char byte
Definition: types.h:22
void end_msg()
Definition: pipe.cpp:166
static const message_id LAST_MESSAGE
Definition: pipe.h:52
bool end_of_data() const
Definition: pipe.cpp:98
Pipe(Filter *=0, Filter *=0, Filter *=0, Filter *=0)
Definition: pipe.cpp:34
size_t size() const
Definition: secmem.h:29
void add(class SecureQueue *)
Definition: out_buf.cpp:53
void pop()
Definition: pipe.cpp:255
void set_default_msg(message_id msg)
Definition: pipe.cpp:106
message_id message_count() const
Definition: pipe.cpp:282
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:116
void prepend(Filter *filt)
Definition: pipe.cpp:235
Pipe::message_id message_count() const
Definition: out_buf.cpp:99