| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (c) 2013-2016 Regents of the University of California. |
| * |
| * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
| * |
| * ndn-cxx library is free software: you can redistribute it and/or modify it under the |
| * terms of the GNU Lesser General Public License as published by the Free Software |
| * Foundation, either version 3 of the License, or (at your option) any later version. |
| * |
| * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
| * |
| * You should have received copies of the GNU General Public License and GNU Lesser |
| * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see |
| * <http://www.gnu.org/licenses/>. |
| * |
| * See AUTHORS.md for complete list of ndn-cxx authors and contributors. |
| */ |
| |
| #ifndef NDN_CXX_SECURITY_TRANSFORM_BASE_HPP |
| #define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP |
| |
| #include "../../common.hpp" |
| #include <vector> |
| |
| namespace ndn { |
| namespace security { |
| namespace transform { |
| |
| /** |
| * @file transform-base.hpp |
| * |
| * There are three types of module in a transformation chain: Source, Transform, and Sink. |
| * The ideal usage of the transformation would be: |
| * |
| * source(...) >> transform1(...) >> transform2(...) >> sink(...); |
| * |
| * When error happens in a module, the module will throw out a transform::Error, one |
| * can get the location of the module through the getIndex() method of transform::Error. |
| */ |
| |
| /** |
| * @brief Base class of transformation error |
| */ |
| class Error : public std::runtime_error |
| { |
| public: |
| Error(size_t index, const std::string& what); |
| |
| size_t |
| getIndex() const |
| { |
| return m_index; |
| } |
| |
| private: |
| size_t m_index; |
| }; |
| |
| /** |
| * @brief The downstream interface of a transformation module |
| * |
| * A module can accept input through this interface |
| */ |
| class Downstream |
| { |
| public: |
| virtual |
| ~Downstream() = default; |
| |
| /** |
| * @brief Accept input data and perform transformation. |
| * |
| * An upstream module should call this method to write data into this module. |
| * The written data will be transformed and the result will be written into the next |
| * downstream module. |
| * |
| * An upstream module can keep calling this method to until end() is called, which |
| * indicates the end of input. After that, calling this method will cause Error. |
| * |
| * If a Downstream implementation expects structured input (e.g., hex decoding requires byte-pair), |
| * it should not return less than size if final portion of input is not a complete record. |
| * |
| * @return number of bytes that has been written into this module |
| * @throws Error if this module is closed or transformation error happens. |
| */ |
| size_t |
| write(const uint8_t* buf, size_t size); |
| |
| /** |
| * @brief Close the input interface of a module. |
| * |
| * This method will notify this module that there is no more input and that the module |
| * should finalize transformation. |
| * |
| * Although end() can be invoked multiple times, only the first invocation takes effect. |
| */ |
| void |
| end(); |
| |
| /** |
| * @brief Check if the input interface of a module is closed. |
| */ |
| bool |
| isEnd() const |
| { |
| return m_isEnd; |
| } |
| |
| /** |
| * @brief Set the module index. |
| */ |
| void |
| setIndex(size_t index) |
| { |
| m_index = index; |
| } |
| |
| /** |
| * @brief Get the module index. |
| */ |
| size_t |
| getIndex() const |
| { |
| return m_index; |
| } |
| |
| protected: |
| Downstream(); |
| |
| private: |
| /** |
| * @brief Internal implementation of write method |
| */ |
| virtual size_t |
| doWrite(const uint8_t* buf, size_t size) = 0; |
| |
| /** |
| * @brief Internal implementation of end method |
| */ |
| virtual void |
| doEnd() = 0; |
| |
| private: |
| bool m_isEnd; |
| size_t m_index; |
| }; |
| |
| /** |
| * @brief The upstream interface of a transformation module |
| * |
| * A module can construct subsequent transformation chain through this interface. |
| */ |
| class Upstream |
| { |
| public: |
| virtual |
| ~Upstream() = default; |
| |
| protected: |
| Upstream(); |
| |
| protected: |
| /** |
| * @brief connect to next transformation module |
| */ |
| void |
| appendChain(unique_ptr<Downstream> tail); |
| |
| Downstream* |
| getNext() |
| { |
| return m_next.get(); |
| } |
| |
| protected: |
| unique_ptr<Downstream> m_next; |
| }; |
| |
| /** |
| * @brief Abstraction of an intermediate transformation module |
| */ |
| class Transform : public Upstream, |
| public Downstream, |
| noncopyable |
| { |
| protected: |
| typedef std::vector<uint8_t> OBuffer; |
| |
| Transform(); |
| |
| /** |
| * @brief Read the content from output buffer and write it into next module. |
| * |
| * It is not guaranteed that all the content in output buffer will be flushed to next module. |
| */ |
| void |
| flushOutputBuffer(); |
| |
| /** |
| * @brief Read the all the content from output buffer and write it into next module. |
| * @post isOutputBufferEmpty() returns true. |
| */ |
| void |
| flushAllOutput(); |
| |
| /** |
| * @brief Set output buffer to @p buffer |
| */ |
| void |
| setOutputBuffer(unique_ptr<OBuffer> buffer); |
| |
| /** |
| * @brief Check if output buffer is empty |
| */ |
| bool |
| isOutputBufferEmpty() const; |
| |
| private: |
| /** |
| * @brief Abstraction of data processing in an intermediate module |
| */ |
| size_t |
| doWrite(const uint8_t* data, size_t dataLen) final; |
| |
| /** |
| * @brief Finalize transformation in this module |
| * |
| * This method will not return until all transformation result is written into next module |
| */ |
| void |
| doEnd() final; |
| |
| /** |
| * @brief Process before transformation. |
| * |
| * @pre output buffer is empty. |
| * |
| * This method is invoked before every convert(...) invocation. |
| * |
| * This implementation does nothing. A subclass can override this method to perform |
| * specific pre-transformation procedure, e.g., read partial transformation results into |
| * output buffer. |
| */ |
| virtual void |
| preTransform(); |
| |
| /** |
| * @brief Convert input @p data. |
| * |
| * @return The number of input bytes that have been accepted by the converter. |
| */ |
| virtual size_t |
| convert(const uint8_t* data, size_t dataLen) = 0; |
| |
| /** |
| * @brief Finalize the transformation. |
| * |
| * This implementation only flushes content in output buffer into next module. |
| * A subclass can override this method to perform specific finalization procedure, i.e., |
| * finalize the transformation and flush the result into next module. |
| */ |
| virtual void |
| finalize(); |
| |
| private: |
| unique_ptr<OBuffer> m_oBuffer; |
| size_t m_outputOffset; |
| }; |
| |
| /** |
| * @brief Abstraction of the transformation sink module |
| * |
| * This module does not have next module and can only accept input data |
| */ |
| class Sink : public Downstream, |
| noncopyable |
| { |
| }; |
| |
| /** |
| * @brief Abstraction of the transformation source module |
| * |
| * This module can only accept input data from constructor |
| */ |
| class Source : public Upstream, |
| noncopyable |
| { |
| public: |
| /** |
| * @brief Connect to an intermediate transformation module. |
| */ |
| Source& |
| operator>>(unique_ptr<Transform> transform); |
| |
| /** |
| * @brief Connect to the last transformation module. |
| * |
| * This method will trigger the source to pump data into the transformation pipeline. |
| */ |
| void |
| operator>>(unique_ptr<Sink> sink); |
| |
| protected: |
| Source(); |
| |
| /** |
| * @brief Pump all data into next transformation module. |
| */ |
| void |
| pump(); |
| |
| /** |
| * @brief Get the source module index (should always be 0). |
| */ |
| size_t |
| getIndex() const |
| { |
| return 0; |
| } |
| |
| private: |
| /** |
| * @brief Internal implementation of pump(). |
| */ |
| virtual void |
| doPump() = 0; |
| |
| private: |
| size_t m_nModules; // count of modules in the chain starting from this Source |
| }; |
| |
| } // namespace transform |
| } // namespace security |
| } // namespace ndn |
| |
| #endif // NDN_CXX_SECURITY_TRANSFORM_BASE_HPP |