10#include <botan/assert.h>
11#include <botan/internal/fmt.h>
12#include <botan/internal/mem_utils.h>
13#include <botan/internal/out_buf.h>
14#include <botan/internal/secqueue.h>
25class Null_Filter final :
public Filter {
27 void write(
const uint8_t input[],
size_t length)
override { send(input, length); }
29 std::string name()
const override {
return "Null"; }
36 m_pipe(std::exchange(other.m_pipe,
nullptr)),
37 m_outputs(std::move(other.m_outputs)),
38 m_default_read(std::exchange(other.m_default_read, 0)),
39 m_inside_msg(std::exchange(other.m_inside_msg,
false)) {}
46const Output_Buffers& Pipe::outputs()
const {
62Pipe::Pipe(std::initializer_list<Filter*> args) : m_pipe(nullptr), m_default_read(0), m_inside_msg(false) {
63 m_outputs = std::make_unique<Output_Buffers>();
65 for(
auto* arg : args) {
89void Pipe::destruct(
Filter* to_kill) {
90 if(to_kill ==
nullptr) {
94 if(
dynamic_cast<SecureQueue*
>(to_kill) !=
nullptr) {
98 for(
size_t j = 0; j != to_kill->total_ports(); ++j) {
99 destruct(to_kill->m_next[j]);
118 m_default_read = msg;
126 write(input, length);
166 throw Invalid_State(
"Pipe::start_msg: Message was already started");
168 if(m_pipe ==
nullptr) {
169 m_pipe =
new Null_Filter;
171 find_endpoints(m_pipe);
181 throw Invalid_State(
"Pipe::end_msg: Message was already ended");
183 m_pipe->finish_msg();
184 clear_endpoints(m_pipe);
185 if(
dynamic_cast<Null_Filter*
>(m_pipe) !=
nullptr) {
189 m_inside_msg =
false;
197void Pipe::find_endpoints(
Filter* f) {
198 for(
size_t j = 0; j != f->total_ports(); ++j) {
199 if(f->m_next[j] !=
nullptr &&
dynamic_cast<SecureQueue*
>(f->m_next[j]) ==
nullptr) {
200 find_endpoints(f->m_next[j]);
202 SecureQueue* q =
new SecureQueue;
212void Pipe::clear_endpoints(
Filter* f) {
216 for(
size_t j = 0; j != f->total_ports(); ++j) {
217 if(f->m_next[j] !=
nullptr &&
dynamic_cast<SecureQueue*
>(f->m_next[j]) !=
nullptr) {
218 f->m_next[j] =
nullptr;
220 clear_endpoints(f->m_next[j]);
230 throw Invalid_State(
"Cannot call Pipe::append_filter after start_msg");
242 throw Invalid_State(
"Cannot call Pipe::prepend_filter after start_msg");
251void Pipe::do_append(
Filter* filter) {
252 if(filter ==
nullptr) {
255 if(
dynamic_cast<SecureQueue*
>(filter) !=
nullptr) {
256 throw Invalid_Argument(
"Pipe::append: SecureQueue cannot be used");
258 if(filter->m_owned) {
259 throw Invalid_Argument(
"Filters cannot be shared among multiple Pipes");
263 throw Invalid_State(
"Cannot append to a Pipe while it is processing");
266 filter->m_owned =
true;
268 if(m_pipe ==
nullptr) {
271 m_pipe->attach(filter);
278void Pipe::do_prepend(
Filter* filter) {
280 throw Invalid_State(
"Cannot prepend to a Pipe while it is processing");
282 if(filter ==
nullptr) {
285 if(
dynamic_cast<SecureQueue*
>(filter) !=
nullptr) {
286 throw Invalid_Argument(
"Pipe::prepend: SecureQueue cannot be used");
288 if(filter->m_owned) {
289 throw Invalid_Argument(
"Filters cannot be shared among multiple Pipes");
292 filter->m_owned =
true;
294 if(m_pipe !=
nullptr) {
295 filter->attach(m_pipe);
305 throw Invalid_State(
"Cannot pop off a Pipe while it is processing");
308 if(m_pipe ==
nullptr) {
312 if(m_pipe->total_ports() > 1) {
313 throw Invalid_State(
"Cannot pop off a Filter with multiple ports");
316 size_t to_remove = m_pipe->owns() + 1;
318 while(to_remove > 0) {
319 const std::unique_ptr<Filter> to_destroy(m_pipe);
322 m_pipe = (m_pipe->total_ports() > 0) ? m_pipe->m_next[0] :
nullptr;
331 return outputs().message_count();
#define BOTAN_STATE_CHECK(expr)
DataSource()=default
Default constructor.
Invalid_Argument(std::string_view msg)
void add(SecureQueue *queue)
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