NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
base64-decode.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "base64-decode.hpp"
23 #include "../../encoding/buffer.hpp"
24 #include "../detail/openssl.hpp"
25 
26 namespace ndn {
27 namespace security {
28 namespace transform {
29 
35 {
36 public:
37  Impl()
38  : m_base64(BIO_new(BIO_f_base64()))
39  , m_source(BIO_new(BIO_s_mem()))
40  {
41  // Input may not be written in a single time.
42  // Do not return EOF when source is empty unless explicitly requested
43  BIO_set_mem_eof_return(m_source, -1);
44 
45  // connect base64 transform to the data source.
46  BIO_push(m_base64, m_source);
47  }
48 
50  {
51  BIO_free_all(m_base64);
52  }
53 
54 public:
55  BIO* m_base64;
56  BIO* m_source; // BIO_f_base64 alone does not work without a source
57 };
58 
59 static const size_t BUFFER_LENGTH = 1024;
60 
61 Base64Decode::Base64Decode(bool expectNewlineEvery64Bytes)
62  : m_impl(new Impl)
63 {
64  if (!expectNewlineEvery64Bytes)
65  BIO_set_flags(m_impl->m_base64, BIO_FLAGS_BASE64_NO_NL);
66 }
67 
68 void
69 Base64Decode::preTransform()
70 {
71  while (isOutputBufferEmpty()) {
72  fillOutputBuffer();
73  if (isOutputBufferEmpty()) // nothing to read from BIO, return
74  return;
75 
77  }
78 }
79 
80 size_t
81 Base64Decode::convert(const uint8_t* buf, size_t size)
82 {
83  int wLen = BIO_write(m_impl->m_source, buf, size);
84 
85  if (wLen <= 0) { // fail to write data
86  if (!BIO_should_retry(m_impl->m_source)) {
87  // we haven't written everything but some error happens, and we cannot retry
88  BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
89  }
90  return 0;
91  }
92  else { // update number of bytes written
93  return wLen;
94  }
95 }
96 
97 void
98 Base64Decode::finalize()
99 {
100  BIO_set_mem_eof_return(m_impl->m_source, 0);
101 
102  fillOutputBuffer();
103 
104  while (!isOutputBufferEmpty()) {
106  if (isOutputBufferEmpty())
107  fillOutputBuffer();
108  }
109 }
110 
111 void
112 Base64Decode::fillOutputBuffer()
113 {
114  // OpenSSL base64 BIO cannot give us the number bytes of partial decoded result,
115  // so we just try to read a chunk.
116  auto buffer = make_unique<OBuffer>(BUFFER_LENGTH);
117  int rLen = BIO_read(m_impl->m_base64, &(*buffer)[0], buffer->size());
118  if (rLen <= 0)
119  return;
120 
121  if (static_cast<size_t>(rLen) < buffer->size())
122  buffer->erase(buffer->begin() + rLen, buffer->end());
123 
124  setOutputBuffer(std::move(buffer));
125 }
126 
127 unique_ptr<Transform>
128 base64Decode(bool expectNewlineEvery64Bytes)
129 {
130  return make_unique<Base64Decode>(expectNewlineEvery64Bytes);
131 }
132 
133 } // namespace transform
134 } // namespace security
135 } // namespace ndn
Copyright (c) 2011-2015 Regents of the University of California.
size_t getIndex() const
Get the module index.
unique_ptr< Transform > base64Decode(bool expectNewlineEvery64Bytes)
bool isOutputBufferEmpty() const
Check if output buffer is empty.
static const size_t BUFFER_LENGTH
The implementation class which contains the internal state of the filter which includes openssl speci...
void setOutputBuffer(unique_ptr< OBuffer > buffer)
Set output buffer to buffer.
Base class of transformation error.
Base64Decode(bool expectNewlineEvery64Bytes=true)
Create a base64 decoding module.
void flushOutputBuffer()
Read the content from output buffer and write it into next module.