10#include <botan/internal/fmt.h>
11#include <botan/internal/mem_utils.h>
12#include <botan/internal/out_buf.h>
13#include <botan/internal/secqueue.h>
23class Null_Filter final :
public Filter {
25 void write(
const uint8_t input[],
size_t length)
override { send(input, length); }
27 std::string name()
const override {
return "Null"; }
45Pipe::Pipe(std::initializer_list<Filter*> args) : m_pipe(nullptr), m_default_read(0), m_inside_msg(false) {
46 m_outputs = std::make_unique<Output_Buffers>();
48 for(
auto* arg : args) {
72void Pipe::destruct(
Filter* to_kill) {
73 if(to_kill ==
nullptr) {
77 if(
dynamic_cast<SecureQueue*
>(to_kill) !=
nullptr) {
81 for(
size_t j = 0; j != to_kill->total_ports(); ++j) {
82 destruct(to_kill->m_next[j]);
101 m_default_read = msg;
109 write(input, length);
149 throw Invalid_State(
"Pipe::start_msg: Message was already started");
151 if(m_pipe ==
nullptr) {
152 m_pipe =
new Null_Filter;
154 find_endpoints(m_pipe);
164 throw Invalid_State(
"Pipe::end_msg: Message was already ended");
166 m_pipe->finish_msg();
167 clear_endpoints(m_pipe);
168 if(
dynamic_cast<Null_Filter*
>(m_pipe) !=
nullptr) {
172 m_inside_msg =
false;
180void Pipe::find_endpoints(
Filter* f) {
181 for(
size_t j = 0; j != f->total_ports(); ++j) {
182 if(f->m_next[j] !=
nullptr &&
dynamic_cast<SecureQueue*
>(f->m_next[j]) ==
nullptr) {
183 find_endpoints(f->m_next[j]);
185 SecureQueue* q =
new SecureQueue;
195void Pipe::clear_endpoints(
Filter* f) {
199 for(
size_t j = 0; j != f->total_ports(); ++j) {
200 if(f->m_next[j] !=
nullptr &&
dynamic_cast<SecureQueue*
>(f->m_next[j]) !=
nullptr) {
201 f->m_next[j] =
nullptr;
203 clear_endpoints(f->m_next[j]);
212 if(m_outputs->message_count() != 0) {
213 throw Invalid_State(
"Cannot call Pipe::append_filter after start_msg");
224 if(m_outputs->message_count() != 0) {
225 throw Invalid_State(
"Cannot call Pipe::prepend_filter after start_msg");
234void Pipe::do_append(
Filter* filter) {
235 if(filter ==
nullptr) {
238 if(
dynamic_cast<SecureQueue*
>(filter) !=
nullptr) {
239 throw Invalid_Argument(
"Pipe::append: SecureQueue cannot be used");
241 if(filter->m_owned) {
242 throw Invalid_Argument(
"Filters cannot be shared among multiple Pipes");
246 throw Invalid_State(
"Cannot append to a Pipe while it is processing");
249 filter->m_owned =
true;
251 if(m_pipe ==
nullptr) {
254 m_pipe->attach(filter);
261void Pipe::do_prepend(
Filter* filter) {
263 throw Invalid_State(
"Cannot prepend to a Pipe while it is processing");
265 if(filter ==
nullptr) {
268 if(
dynamic_cast<SecureQueue*
>(filter) !=
nullptr) {
269 throw Invalid_Argument(
"Pipe::prepend: SecureQueue cannot be used");
271 if(filter->m_owned) {
272 throw Invalid_Argument(
"Filters cannot be shared among multiple Pipes");
275 filter->m_owned =
true;
277 if(m_pipe !=
nullptr) {
278 filter->attach(m_pipe);
288 throw Invalid_State(
"Cannot pop off a Pipe while it is processing");
291 if(m_pipe ==
nullptr) {
295 if(m_pipe->total_ports() > 1) {
296 throw Invalid_State(
"Cannot pop off a Filter with multiple ports");
299 size_t to_remove = m_pipe->owns() + 1;
301 while(to_remove > 0) {
302 std::unique_ptr<Filter> to_destroy(m_pipe);
303 m_pipe = m_pipe->m_next[0];
312 return m_outputs->message_count();
Invalid_Argument(std::string_view msg)
Invalid_Message_Number(std::string_view where, message_id msg)
static const message_id LAST_MESSAGE
void process_msg(const uint8_t in[], size_t length)
BOTAN_FUTURE_EXPLICIT Pipe(Filter *f1=nullptr, Filter *f2=nullptr, Filter *f3=nullptr, Filter *f4=nullptr)
void write(const uint8_t in[], size_t length)
static const message_id DEFAULT_MESSAGE
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
void prepend_filter(Filter *filt)
void append(Filter *filt)
void append_filter(Filter *filt)
message_id message_count() const
void prepend(Filter *filt)
bool end_of_data() const override
void set_default_msg(message_id msg)
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
std::string fmt(std::string_view format, const T &... args)
std::vector< T, secure_allocator< T > > secure_vector