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
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 */
56 Pipe::~Pipe()
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 */
76 void Pipe::reset()
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 */
106 void Pipe::set_default_msg(message_id msg)
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 */
126 void Pipe::process_msg(const MemoryRegion<byte>& input)
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 */
142 void Pipe::process_msg(DataSource& input)
143 {
144 start_msg();
145 write(input);
146 end_msg();
147 }
148
149 /*
150 * Start a new message
151 */
152 void Pipe::start_msg()
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 */
166 void Pipe::end_msg()
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 */
282 Pipe::message_id Pipe::message_count() const
283 {
284 return outputs->message_count();
285 }
286
287 /*
288 * Static Member Variables
289 */
290 const Pipe::message_id Pipe::LAST_MESSAGE =
291 static_cast<Pipe::message_id>(-2);
292
293 const Pipe::message_id Pipe::DEFAULT_MESSAGE =
294 static_cast<Pipe::message_id>(-1);
295
296 }
Botan::Pipe::start_msg
void start_msg()
Definition: pipe.cpp:152
Botan::Pipe::remaining
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
Definition: pipe_rw.cpp:138
Botan::Pipe::append
void append(Filter *filt)
Definition: pipe.cpp:215
Botan::SecureQueue
Definition: secqueue.h:19
Botan::Pipe::write
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
Botan::Pipe::message_id
size_t message_id
Definition: pipe.h:31
Botan::Invalid_State
Definition: exceptn.h:25
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::Output_Buffers
Definition: out_buf.h:20
Botan::DataSource
Definition: data_src.h:20
Botan::Output_Buffers::retire
void retire()
Definition: out_buf.cpp:66
Botan::Pipe::reset
void reset()
Definition: pipe.cpp:76
Botan::Pipe::DEFAULT_MESSAGE
static const message_id DEFAULT_MESSAGE
Definition: pipe.h:57
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::Pipe::end_msg
void end_msg()
Definition: pipe.cpp:166
Botan::Pipe::LAST_MESSAGE
static const message_id LAST_MESSAGE
Definition: pipe.h:52
Botan::Filter
Definition: filter.h:19
Botan::Output_Buffers::message_count
Pipe::message_id message_count() const
Definition: out_buf.cpp:99
Botan::Pipe::Pipe
Pipe(Filter *=0, Filter *=0, Filter *=0, Filter *=0)
Definition: pipe.cpp:34
Botan::MemoryRegion< byte >
Botan
Definition: algo_base.h:14
Botan::Pipe::~Pipe
~Pipe()
Definition: pipe.cpp:56
Botan::Pipe::message_count
message_id message_count() const
Definition: pipe.cpp:282
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::Output_Buffers::add
void add(class SecureQueue *)
Definition: out_buf.cpp:53
Botan::Pipe::end_of_data
bool end_of_data() const
Definition: pipe.cpp:98
Botan::Pipe::pop
void pop()
Definition: pipe.cpp:255
Botan::Pipe::set_default_msg
void set_default_msg(message_id msg)
Definition: pipe.cpp:106
Botan::Pipe::process_msg
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:116
Botan::Pipe::prepend
void prepend(Filter *filt)
Definition: pipe.cpp:235