Botan  1.11.15
src/lib/filters/pipe.h
Go to the documentation of this file.
00001 /*
00002 * Pipe
00003 * (C) 1999-2007 Jack Lloyd
00004 *     2012 Markus Wanner
00005 *
00006 * Botan is released under the Simplified BSD License (see license.txt)
00007 */
00008 
00009 #ifndef BOTAN_PIPE_H__
00010 #define BOTAN_PIPE_H__
00011 
00012 #include <botan/data_src.h>
00013 #include <botan/filter.h>
00014 #include <botan/exceptn.h>
00015 #include <initializer_list>
00016 #include <iosfwd>
00017 
00018 namespace Botan {
00019 
00020 /**
00021 * This class represents pipe objects.
00022 * A set of filters can be placed into a pipe, and information flows
00023 * through the pipe until it reaches the end, where the output is
00024 * collected for retrieval.  If you're familiar with the Unix shell
00025 * environment, this design will sound quite familiar.
00026 */
00027 class BOTAN_DLL Pipe : public DataSource
00028    {
00029    public:
00030       /**
00031       * An opaque type that identifies a message in this Pipe
00032       */
00033       typedef size_t message_id;
00034 
00035       /**
00036       * Exception if you use an invalid message as an argument to
00037       * read, remaining, etc
00038       */
00039       struct BOTAN_DLL Invalid_Message_Number : public Invalid_Argument
00040          {
00041          /**
00042          * @param where the error occured
00043          * @param msg the invalid message id that was used
00044          */
00045          Invalid_Message_Number(const std::string& where, message_id msg) :
00046             Invalid_Argument("Pipe::" + where + ": Invalid message number " +
00047                              std::to_string(msg))
00048             {}
00049          };
00050 
00051       /**
00052       * A meta-id for whatever the last message is
00053       */
00054       static const message_id LAST_MESSAGE;
00055 
00056       /**
00057       * A meta-id for the default message (set with set_default_msg)
00058       */
00059       static const message_id DEFAULT_MESSAGE;
00060 
00061       /**
00062       * Write input to the pipe, i.e. to its first filter.
00063       * @param in the byte array to write
00064       * @param length the length of the byte array in
00065       */
00066       void write(const byte in[], size_t length);
00067 
00068       /**
00069       * Write input to the pipe, i.e. to its first filter.
00070       * @param in the secure_vector containing the data to write
00071       */
00072       void write(const secure_vector<byte>& in)
00073          { write(in.data(), in.size()); }
00074 
00075       /**
00076       * Write input to the pipe, i.e. to its first filter.
00077       * @param in the std::vector containing the data to write
00078       */
00079       void write(const std::vector<byte>& in)
00080          { write(in.data(), in.size()); }
00081 
00082       /**
00083       * Write input to the pipe, i.e. to its first filter.
00084       * @param in the string containing the data to write
00085       */
00086       void write(const std::string& in);
00087 
00088       /**
00089       * Write input to the pipe, i.e. to its first filter.
00090       * @param in the DataSource to read the data from
00091       */
00092       void write(DataSource& in);
00093 
00094       /**
00095       * Write input to the pipe, i.e. to its first filter.
00096       * @param in a single byte to be written
00097       */
00098       void write(byte in);
00099 
00100       /**
00101       * Perform start_msg(), write() and end_msg() sequentially.
00102       * @param in the byte array containing the data to write
00103       * @param length the length of the byte array to write
00104       */
00105       void process_msg(const byte in[], size_t length);
00106 
00107       /**
00108       * Perform start_msg(), write() and end_msg() sequentially.
00109       * @param in the secure_vector containing the data to write
00110       */
00111       void process_msg(const secure_vector<byte>& in);
00112 
00113       /**
00114       * Perform start_msg(), write() and end_msg() sequentially.
00115       * @param in the secure_vector containing the data to write
00116       */
00117       void process_msg(const std::vector<byte>& in);
00118 
00119       /**
00120       * Perform start_msg(), write() and end_msg() sequentially.
00121       * @param in the string containing the data to write
00122       */
00123       void process_msg(const std::string& in);
00124 
00125       /**
00126       * Perform start_msg(), write() and end_msg() sequentially.
00127       * @param in the DataSource providing the data to write
00128       */
00129       void process_msg(DataSource& in);
00130 
00131       /**
00132       * Find out how many bytes are ready to read.
00133       * @param msg the number identifying the message
00134       * for which the information is desired
00135       * @return number of bytes that can still be read
00136       */
00137       size_t remaining(message_id msg = DEFAULT_MESSAGE) const;
00138 
00139       /**
00140       * Read the default message from the pipe. Moves the internal
00141       * offset so that every call to read will return a new portion of
00142       * the message.
00143       *
00144       * @param output the byte array to write the read bytes to
00145       * @param length the length of the byte array output
00146       * @return number of bytes actually read into output
00147       */
00148       size_t read(byte output[], size_t length);
00149 
00150       /**
00151       * Read a specified message from the pipe. Moves the internal
00152       * offset so that every call to read will return a new portion of
00153       * the message.
00154       * @param output the byte array to write the read bytes to
00155       * @param length the length of the byte array output
00156       * @param msg the number identifying the message to read from
00157       * @return number of bytes actually read into output
00158       */
00159       size_t read(byte output[], size_t length, message_id msg);
00160 
00161       /**
00162       * Read a single byte from the pipe. Moves the internal offset so
00163       * that every call to read will return a new portion of the
00164       * message.
00165       *
00166       * @param output the byte to write the result to
00167       * @param msg the message to read from
00168       * @return number of bytes actually read into output
00169       */
00170       size_t read(byte& output, message_id msg = DEFAULT_MESSAGE);
00171 
00172       /**
00173       * Read the full contents of the pipe.
00174       * @param msg the number identifying the message to read from
00175       * @return secure_vector holding the contents of the pipe
00176       */
00177       secure_vector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
00178 
00179       /**
00180       * Read the full contents of the pipe.
00181       * @param msg the number identifying the message to read from
00182       * @return string holding the contents of the pipe
00183       */
00184       std::string read_all_as_string(message_id = DEFAULT_MESSAGE);
00185 
00186       /** Read from the default message but do not modify the internal
00187       * offset. Consecutive calls to peek() will return portions of
00188       * the message starting at the same position.
00189       * @param output the byte array to write the peeked message part to
00190       * @param length the length of the byte array output
00191       * @param offset the offset from the current position in message
00192       * @return number of bytes actually peeked and written into output
00193       */
00194       size_t peek(byte output[], size_t length, size_t offset) const;
00195 
00196       /** Read from the specified message but do not modify the
00197       * internal offset. Consecutive calls to peek() will return
00198       * portions of the message starting at the same position.
00199       * @param output the byte array to write the peeked message part to
00200       * @param length the length of the byte array output
00201       * @param offset the offset from the current position in message
00202       * @param msg the number identifying the message to peek from
00203       * @return number of bytes actually peeked and written into output
00204       */
00205       size_t peek(byte output[], size_t length,
00206                   size_t offset, message_id msg) const;
00207 
00208       /** Read a single byte from the specified message but do not
00209       * modify the internal offset. Consecutive calls to peek() will
00210       * return portions of the message starting at the same position.
00211       * @param output the byte to write the peeked message byte to
00212       * @param offset the offset from the current position in message
00213       * @param msg the number identifying the message to peek from
00214       * @return number of bytes actually peeked and written into output
00215       */
00216       size_t peek(byte& output, size_t offset,
00217                   message_id msg = DEFAULT_MESSAGE) const;
00218 
00219       /**
00220       * @return the number of bytes read from the default message.
00221       */
00222       size_t get_bytes_read() const;
00223 
00224       /**
00225       * @return the number of bytes read from the specified message.
00226       */
00227       size_t get_bytes_read(message_id msg = DEFAULT_MESSAGE) const;
00228 
00229       /**
00230       * @return currently set default message
00231       */
00232       size_t default_msg() const { return default_read; }
00233 
00234       /**
00235       * Set the default message
00236       * @param msg the number identifying the message which is going to
00237       * be the new default message
00238       */
00239       void set_default_msg(message_id msg);
00240 
00241       /**
00242       * Get the number of messages the are in this pipe.
00243       * @return number of messages the are in this pipe
00244       */
00245       message_id message_count() const;
00246 
00247       /**
00248       * Test whether this pipe has any data that can be read from.
00249       * @return true if there is more data to read, false otherwise
00250       */
00251       bool end_of_data() const;
00252 
00253       /**
00254       * Start a new message in the pipe. A potential other message in this pipe
00255       * must be closed with end_msg() before this function may be called.
00256       */
00257       void start_msg();
00258 
00259       /**
00260       * End the current message.
00261       */
00262       void end_msg();
00263 
00264       /**
00265       * Insert a new filter at the front of the pipe
00266       * @param filt the new filter to insert
00267       */
00268       void prepend(Filter* filt);
00269 
00270       /**
00271       * Insert a new filter at the back of the pipe
00272       * @param filt the new filter to insert
00273       */
00274       void append(Filter* filt);
00275 
00276       /**
00277       * Remove the first filter at the front of the pipe.
00278       */
00279       void pop();
00280 
00281       /**
00282       * Reset this pipe to an empty pipe.
00283       */
00284       void reset();
00285 
00286       /**
00287       * Construct a Pipe of up to four filters. The filters are set up
00288       * in the same order as the arguments.
00289       */
00290       Pipe(Filter* = nullptr, Filter* = nullptr,
00291            Filter* = nullptr, Filter* = nullptr);
00292 
00293       /**
00294       * Construct a Pipe from a list of filters
00295       * @param filters the set of filters to use
00296       */
00297       Pipe(std::initializer_list<Filter*> filters);
00298 
00299       Pipe(const Pipe&) = delete;
00300       Pipe& operator=(const Pipe&) = delete;
00301 
00302       ~Pipe();
00303    private:
00304       void init();
00305       void destruct(Filter*);
00306       void find_endpoints(Filter*);
00307       void clear_endpoints(Filter*);
00308 
00309       message_id get_message_no(const std::string&, message_id) const;
00310 
00311       Filter* pipe;
00312       class Output_Buffers* outputs;
00313       message_id default_read;
00314       bool inside_msg;
00315    };
00316 
00317 /**
00318 * Stream output operator; dumps the results from pipe's default
00319 * message to the output stream.
00320 * @param out an output stream
00321 * @param pipe the pipe
00322 */
00323 BOTAN_DLL std::ostream& operator<<(std::ostream& out, Pipe& pipe);
00324 
00325 /**
00326 * Stream input operator; dumps the remaining bytes of input
00327 * to the (assumed open) pipe message.
00328 * @param in the input stream
00329 * @param pipe the pipe
00330 */
00331 BOTAN_DLL std::istream& operator>>(std::istream& in, Pipe& pipe);
00332 
00333 }
00334 
00335 #if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
00336   #include <botan/fd_unix.h>
00337 #endif
00338 
00339 #endif