base64-encode.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2021 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 
23 #include "ndn-cxx/security/impl/openssl.hpp"
24 
25 namespace ndn {
26 namespace security {
27 namespace transform {
28 
29 class Base64Encode::Impl : boost::noncopyable
30 {
31 public:
32  Impl()
33  : m_base64(BIO_new(BIO_f_base64()))
34  , m_sink(BIO_new(BIO_s_mem()))
35  {
36  // connect base64 transform to the data sink.
37  BIO_push(m_base64, m_sink);
38  }
39 
40  ~Impl()
41  {
42  BIO_free_all(m_base64);
43  }
44 
45 public:
46  BIO* m_base64;
47  BIO* m_sink; // BIO_f_base64 alone does not work without a sink
48 };
49 
50 
52  : m_impl(make_unique<Impl>())
53 {
54  if (!needBreak)
55  BIO_set_flags(m_impl->m_base64, BIO_FLAGS_BASE64_NO_NL);
56 }
57 
58 Base64Encode::~Base64Encode() = default;
59 
60 void
61 Base64Encode::preTransform()
62 {
63  fillOutputBuffer();
64 }
65 
66 size_t
67 Base64Encode::convert(span<const uint8_t> data)
68 {
69  if (data.empty())
70  return 0;
71 
72  int wLen = BIO_write(m_impl->m_base64, data.data(), data.size());
73 
74  if (wLen <= 0) { // fail to write data
75  if (!BIO_should_retry(m_impl->m_base64)) {
76  // we haven't written everything but some error happens, and we cannot retry
77  NDN_THROW(Error(getIndex(), "Failed to accept more input"));
78  }
79  return 0;
80  }
81  else { // update number of bytes written
82  fillOutputBuffer();
83  return wLen;
84  }
85 }
86 
87 void
88 Base64Encode::finalize()
89 {
90  if (BIO_flush(m_impl->m_base64) != 1)
91  NDN_THROW(Error(getIndex(), "Failed to flush"));
92 
93  while (!isConverterEmpty()) {
94  fillOutputBuffer();
95  while (!isOutputBufferEmpty()) {
97  }
98  }
99 }
100 
101 void
102 Base64Encode::fillOutputBuffer()
103 {
104  int nRead = BIO_pending(m_impl->m_sink);
105  if (nRead <= 0)
106  return;
107 
108  // there is something to read from BIO
109  auto buffer = make_unique<OBuffer>(nRead);
110  int rLen = BIO_read(m_impl->m_sink, buffer->data(), nRead);
111  if (rLen < 0)
112  return;
113 
114  if (rLen < nRead)
115  buffer->erase(buffer->begin() + rLen, buffer->end());
116 
117  setOutputBuffer(std::move(buffer));
118 }
119 
120 bool
121 Base64Encode::isConverterEmpty()
122 {
123  return BIO_pending(m_impl->m_sink) <= 0;
124 }
125 
126 unique_ptr<Transform>
127 base64Encode(bool needBreak)
128 {
129  return make_unique<Base64Encode>(needBreak);
130 }
131 
132 } // namespace transform
133 } // namespace security
134 } // namespace ndn
Base64Encode(bool needBreak=true)
Create a base64 encoding module.
size_t getIndex() const
Get the module index.
void setOutputBuffer(unique_ptr< OBuffer > buffer)
Set output buffer to buffer.
bool isOutputBufferEmpty() const
Check if output buffer is empty.
void flushOutputBuffer()
Read the content from output buffer and write it into next module.
#define NDN_THROW(e)
Definition: exception.hpp:61
unique_ptr< Transform > base64Encode(bool needBreak)
Definition: data.cpp:25