Botan 1.10.17
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
13namespace Botan {
14
15namespace {
16
17/*
18* A Filter that does nothing
19*/
20class 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*/
35 {
36 init();
37 append(f1);
38 append(f2);
39 append(f3);
40 append(f4);
41 }
42
43/*
44* Pipe Constructor
45*/
46Pipe::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*/
65void 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*/
86void 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*/
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*/
116void 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*/
134void 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*/
185void 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*/
201void 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*/
215void 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*/
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*/
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}
size_t size() const
Definition secmem.h:29
void add(class SecureQueue *)
Definition out_buf.cpp:53
bool end_of_data() const
Definition pipe.cpp:98
size_t message_id
Definition pipe.h:31
static const message_id LAST_MESSAGE
Definition pipe.h:52
Pipe(Filter *=0, Filter *=0, Filter *=0, Filter *=0)
Definition pipe.cpp:34
void pop()
Definition pipe.cpp:255
void end_msg()
Definition pipe.cpp:166
static const message_id DEFAULT_MESSAGE
Definition pipe.h:57
void write(const byte in[], size_t length)
Definition pipe_rw.cpp:34
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
Definition pipe_rw.cpp:138
void process_msg(const byte in[], size_t length)
Definition pipe.cpp:116
void append(Filter *filt)
Definition pipe.cpp:215
void start_msg()
Definition pipe.cpp:152
message_id message_count() const
Definition pipe.cpp:282
void reset()
Definition pipe.cpp:76
void prepend(Filter *filt)
Definition pipe.cpp:235
void set_default_msg(message_id msg)
Definition pipe.cpp:106
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
Invalid_State(const std::string &err)
Definition exceptn.h:27