blob: 5e3a72b685b6acec678d79d82cfb147192a06653 [file] [log] [blame]
Yingdi Yu3168c302015-07-04 16:45:40 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#ifndef NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
23#define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
24
25#include "../../common.hpp"
Yingdi Yu38317e52015-07-22 13:58:02 -070026#include <vector>
Yingdi Yu3168c302015-07-04 16:45:40 -070027
28namespace ndn {
29namespace security {
30namespace transform {
31
32/**
33 * @file transform-base.hpp
34 *
35 * There are three types of module in a transformation chain: Source, Transform, and Sink.
36 * The ideal usage of the transformation would be:
37 *
38 * source(...) >> transform1(...) >> transform2(...) >> sink(...);
39 *
40 * When error happens in a module, the module will throw out a transform::Error, one
41 * can get the location of the module through the getIndex() method of transform::Error.
42 */
43
44/**
45 * @brief Base class of transformation error
46 */
47class Error : public std::runtime_error
48{
49public:
50 Error(size_t index, const std::string& what);
51
52 size_t
53 getIndex() const
54 {
55 return m_index;
56 }
57
58private:
59 size_t m_index;
60};
61
62/**
63 * @brief The downstream interface of a transformation module
64 *
65 * A module can accept input through this interface
66 */
67class Downstream
68{
69public:
70 /**
71 * @brief Accept input data and perform transformation.
72 *
73 * An upstream module should call this method to write data into this module.
74 * The written data will be transformed and the result will be written into the next
75 * downstream module.
76 *
77 * An upstream module can keep calling this method to until end() is called, which
78 * indicates the end of input. After that, calling this method will cause Error.
79 *
80 * If a Downstream implementation expects structured input (e.g., hex decoding requires byte-pair),
81 * it should not return less than size if final portion of input is not a complete record.
82 *
83 * @return number of bytes that has been written into this module
84 * @throws Error if this module is closed or transformation error happens.
85 */
86 size_t
87 write(const uint8_t* buf, size_t size);
88
89 /**
90 * @brief Close the input interface of a module.
91 *
92 * This method will notify this module that there is no more input and that the module
93 * should finalize transformation.
94 *
95 * Although end() can be invoked multiple times, only the first invocation takes effect.
96 */
97 void
98 end();
99
100 /**
101 * @brief Check if the input interface of a module is closed.
102 */
103 bool
104 isEnd() const
105 {
106 return m_isEnd;
107 }
108
109 /**
110 * @brief Set the module index.
111 */
112 void
113 setIndex(size_t index)
114 {
115 m_index = index;
116 }
117
118 /**
119 * @brief Get the module index.
120 */
121 size_t
122 getIndex() const
123 {
124 return m_index;
125 }
126
127protected:
128 Downstream();
129
130private:
131 /**
132 * @brief Internal implementation of write method
133 */
134 virtual size_t
135 doWrite(const uint8_t* buf, size_t size) = 0;
136
137 /**
138 * @brief Internal implementation of end method
139 */
140 virtual void
141 doEnd() = 0;
142
143private:
144 bool m_isEnd;
145 size_t m_index;
146};
147
148/**
149 * @brief The upstream interface of a transformation module
150 *
151 * A module can construct subsequent transformation chain through this interface.
152 */
153class Upstream
154{
155protected:
156 Upstream();
157
158protected:
159 /**
160 * @brief connect to next transformation module
161 */
162 void
163 appendChain(unique_ptr<Downstream> tail);
164
165 Downstream*
166 getNext()
167 {
168 return m_next.get();
169 }
170
171protected:
172 unique_ptr<Downstream> m_next;
173};
174
175/**
176 * @brief Abstraction of an intermediate transformation module
177 */
178class Transform : public Upstream,
179 public Downstream,
180 noncopyable
181{
Yingdi Yu38317e52015-07-22 13:58:02 -0700182protected:
183 typedef std::vector<uint8_t> OBuffer;
184
185 Transform();
186
187 /**
188 * @brief Read the content from output buffer and write it into next module.
189 */
190 void
191 flushOutputBuffer();
192
193 /**
194 * @brief Set output buffer to @p buffer
195 */
196 void
197 setOutputBuffer(unique_ptr<OBuffer> buffer);
198
199 /**
200 * @brief Check if output buffer is empty
201 */
202 bool
203 isOutputBufferEmpty() const;
204
205private:
206
207 /**
208 * @brief Abstraction of data processing in an intermediate module
209 */
210 virtual size_t
211 doWrite(const uint8_t* data, size_t dataLen) final;
212
213 /**
214 * @brief Finalize transformation in this module
215 *
216 * This method will not return until all transformation result is written into next module
217 */
218 virtual void
219 doEnd() final;
220
221 /**
222 * @brief Process before transformation.
223 *
224 * @pre output buffer is empty.
225 *
226 * This method is invoked before every convert(...) invocation.
227 *
228 * This implementation does nothing. A subclass can override this method to perform
229 * specific pre-transformation procedure, e.g., read partial transformation results into
230 * output buffer.
231 */
232 virtual void
233 preTransform();
234
235 /**
236 * @brief Convert input @p data.
237 *
238 * @return The number of input bytes that have been accepted by the converter.
239 */
240 virtual size_t
241 convert(const uint8_t* data, size_t dataLen) = 0;
242
243 /**
244 * @brief Finalize the transformation.
245 *
246 * This implementation only flushes content in output buffer into next module.
247 * A subclass can override this method to perform specific finalization procedure, i.e.,
248 * finalize the transformation and flush the result into next module.
249 */
250 virtual void
251 finalize();
252
253private:
254 unique_ptr<OBuffer> m_oBuffer;
255 size_t m_outputOffset;
Yingdi Yu3168c302015-07-04 16:45:40 -0700256};
257
258/**
259 * @brief Abstraction of the transformation sink module
260 *
261 * This module does not have next module and can only accept input data
262 */
263class Sink : public Downstream,
264 noncopyable
265{
266};
267
268/**
269 * @brief Abstraction of the transformation source module
270 *
271 * This module can only accept input data from constructor
272 */
273class Source : public Upstream,
274 noncopyable
275{
276public:
277 /**
278 * @brief Connect to an intermediate transformation module.
279 */
280 Source&
281 operator>>(unique_ptr<Transform> transform);
282
283 /**
284 * @brief Connect to the last transformation module.
285 *
286 * This method will trigger the source to pump data into the transformation pipeline.
287 */
288 void
289 operator>>(unique_ptr<Sink> sink);
290
291protected:
292 Source();
293
294 /**
295 * @brief Pump all data into next transformation module.
296 */
297 void
298 pump();
299
300 /**
301 * @brief Get the source module index (should always be 0).
302 */
303 size_t
304 getIndex() const
305 {
306 return 0;
307 }
308
309private:
310 /**
311 * @brief Internal implementation of pump().
312 */
313 virtual void
314 doPump() = 0;
315
316private:
317 size_t m_nModules; // count of modules in the chain starting from this Source
318};
319
320} // namespace transform
321} // namespace security
322} // namespace ndn
323
324#endif // NDN_CXX_SECURITY_TRANSFORM_BASE_HPP