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"; }
40Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) : Pipe({f1, f2, f3, f4}) {}
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]);
84 delete to_kill; // NOLINT(*owning-memory)
88* Test if the Pipe has any data in it
90bool Pipe::end_of_data() const {
91 return (remaining() == 0);
95* Set the default read message
97void Pipe::set_default_msg(message_id msg) {
98 if(msg >= message_count()) {
101 m_default_read = msg;
105* Process a full message at once
107void Pipe::process_msg(const uint8_t input[], size_t length) {
109 write(input, length);
113void Pipe::process_msg(std::span<const uint8_t> input) {
114 this->process_msg(input.data(), input.size());
118* Process a full message at once
120void Pipe::process_msg(const secure_vector<uint8_t>& input) {
121 this->process_msg(std::span{input});
124void Pipe::process_msg(const std::vector<uint8_t>& input) {
125 this->process_msg(std::span{input});
129* Process a full message at once
131void Pipe::process_msg(std::string_view input) {
132 process_msg(as_span_of_bytes(input));
136* Process a full message at once
138void Pipe::process_msg(DataSource& input) {
147void Pipe::start_msg() {
151 if(m_pipe == nullptr) {
152 m_pipe = new Null_Filter; // NOLINT(*-owning-memory)
154 find_endpoints(m_pipe);
160* End the current message
162void Pipe::end_msg() {
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;
178* Find the endpoints of the Pipe
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; // NOLINT(*-owning-memory)
193* Remove the SecureQueues attached to the Filter
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]);
207void Pipe::append(Filter* filter) {
211void Pipe::append_filter(Filter* filter) {
212 if(m_outputs->message_count() != 0) {
219void Pipe::prepend(Filter* filter) {
223void Pipe::prepend_filter(Filter* filter) {
224 if(m_outputs->message_count() != 0) {
232* Append a Filter to the Pipe
234void Pipe::do_append(Filter* filter) {
235 if(filter == nullptr) {
238 if(dynamic_cast<SecureQueue*>(filter) != nullptr) {
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);
259* Prepend a Filter to the Pipe
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) {
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);
284* Pop a Filter off the 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];
309* Return the number of messages in this Pipe
311Pipe::message_id Pipe::message_count() const {
312 return m_outputs->message_count();
316* Static Member Variables
318const Pipe::message_id Pipe::LAST_MESSAGE = static_cast<Pipe::message_id>(-2);
320const Pipe::message_id Pipe::DEFAULT_MESSAGE = static_cast<Pipe::message_id>(-1);
BOTAN_FUTURE_EXPLICIT Pipe(Filter *f1=nullptr, Filter *f2=nullptr, Filter *f3=nullptr, Filter *f4=nullptr)
void prepend_filter(Filter *filt)
void append(Filter *filt)
void append_filter(Filter *filt)
void prepend(Filter *filt)
void set_default_msg(message_id msg)
int(* final)(unsigned char *, CTX *)
std::string fmt(std::string_view format, const T &... args)