Dangerous SNMP
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
berstream.hpp
1 #pragma once
2 
3 #include "dangerous/snmp/logger.hpp"
4 
5 #include "bytestream.hpp"
6 
7 #include <vector>
8 
9 namespace dangerous { namespace snmp {
10 
16 class BerStream {
17 public:
21  BerStream( ByteStream* byteStream );
22 
26  bool copyTo( std::vector<char>& buffer );
27 
32  unsigned int remainingReadLength() const { return _byteStream->remainingReadLength(); }
33 
38  unsigned int remainingWriteLength() const { return _byteStream->remainingWriteLength(); }
39 
40  /*
41  * Peek functions.
42  */
43 
50  bool peekType( uint8_t& type );
51 
52  /*
53  * Read functions.
54  * All of these functions will advance the read head.
55  */
56 
62  bool readType( uint8_t& type );
63 
69  bool readLength( unsigned int& length );
70 
77  template<typename EncodingClass>
78  bool read( typename EncodingClass::value_type& value );
79 
86  bool readBytes( char* buffer, unsigned int bufferSize, unsigned int& bytesRead );
87 
94  bool readFullTlv( std::vector<char>& buffer );
95 
96  /*
97  * Write functions.
98  * All of these functions will advance the write head.
99  */
100 
106  bool writeType( uint8_t type );
107 
113  bool writeLength( unsigned int encodedLength );
114 
121  template<typename EncodingClass>
122  bool write( const typename EncodingClass::value_type& value );
123 
131  bool writeBytes( const char* buffer, unsigned int bufferSize, unsigned int& bytesWritten );
132 
133 protected:
136 };
137 
144 template<typename EncodingClass>
145 bool BerStream::read( typename EncodingClass::value_type& value ) {
146  uint8_t type = 0;
147  bool status = readType( type );
148  if( ! status ) {
149  if( logger.system( Logger::BYTESTREAM ) ) {
150  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Could not read the type." << std::endl;
151  }
152  return false;
153  }
154 
155  if( logger.system( Logger::BYTESTREAM ) ) {
156  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Looking for a type of " << EncodingClass::TYPE << "." << std::endl;
157  }
158  if( type != EncodingClass::TYPE ) {
159  return false;
160  }
161 
162  unsigned int increment = 0;
163  status = readLength( increment );
164  if( ! status ) {
165  if( logger.system( Logger::BYTESTREAM ) ) {
166  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Could not read the length." << std::endl;
167  }
168  return false;
169  }
170  if( logger.system( Logger::BYTESTREAM ) ) {
171  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Got a length of " << increment << "." << std::endl;
172  }
173  if( increment < 1 ) {
174  return true;
175  }
176 
177  if( logger.system( Logger::BYTESTREAM ) ) {
178  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Reading " << increment << " bytes." << std::endl;
179  }
180  unsigned int bytesRead = 0;
181  char buffer[ increment ];
182  status = readBytes( buffer, increment, bytesRead );
183  if( ! status ) {
184  if( logger.system( Logger::BYTESTREAM ) ) {
185  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Could not read the value bytes." << std::endl;
186  }
187  return false;
188  }
189  status = EncodingClass::read( value, buffer, increment );
190  if( ! status ) {
191  if( logger.system( Logger::BYTESTREAM ) ) {
192  logger.out() << "BerStream: read<" << EncodingClass::NAME << ">: Could not parse the value bytes." << std::endl;
193  }
194  return false;
195  }
196 
197  return true;
198 }
199 
206 template<typename EncodingClass>
207 bool BerStream::write( const typename EncodingClass::value_type& value ) {
208  if( logger.system( Logger::BYTESTREAM ) ) {
209  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Writing a type of " << EncodingClass::TYPE << "." << std::endl;
210  }
211  bool status = writeType( EncodingClass::TYPE );
212  if( ! status ) {
213  if( logger.system( Logger::BYTESTREAM ) ) {
214  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Could not write the type." << std::endl;
215  }
216  return false;
217  }
218 
219  unsigned int encodedLength = EncodingClass::length( value );
220  if( logger.system( Logger::BYTESTREAM ) ) {
221  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Got a length of " << encodedLength << "." << std::endl;
222  }
223  status = writeLength( encodedLength );
224  if( ! status ) {
225  if( logger.system( Logger::BYTESTREAM ) ) {
226  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Could not write the length." << std::endl;
227  }
228  return false;
229  }
230 
231  if( logger.system( Logger::BYTESTREAM ) ) {
232  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Writing " << encodedLength << " bytes." << std::endl;
233  }
234 
235  char buffer[ encodedLength ];
236  status = EncodingClass::write( value, buffer, encodedLength );
237  if( ! status ) {
238  if( logger.system( Logger::BYTESTREAM ) ) {
239  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Could not encode the value." << std::endl;
240  }
241  return false;
242  }
243 
244  unsigned int bytesWritten = 0;
245  status = writeBytes( buffer, encodedLength, bytesWritten );
246  if( ! status ) {
247  if( logger.system( Logger::BYTESTREAM ) ) {
248  logger.out() << "BerStream: write<" << EncodingClass::NAME << ">: Could not write the value." << std::endl;
249  }
250  return false;
251  }
252 
253  return true;
254 }
255 
256 } }
257 
bool write(const typename EncodingClass::value_type &value)
This performs a full, logical write of a kind of encoded data.
Definition: berstream.hpp:207
bool system(System system)
This returns the logging status for the given system.
Definition: logger.hpp:47
BerStream(ByteStream *byteStream)
TODO.
std::ostream & out()
This returns the output stream for the Logger.
Definition: logger.hpp:77
bool readFullTlv(std::vector< char > &buffer)
This reads a full TLV set of data and fills out the whole thing (including the type, the length, and the value) exactly as read.
A ByteStream is an object that is basically a big wrapper around a character buffer.
Definition: bytestream.hpp:30
bool readBytes(char *buffer, unsigned int bufferSize, unsigned int &bytesRead)
This reads an arbitrary amount of bytes into the specified character buffer.
unsigned int remainingReadLength() const
This returns the number of bytes remaining in the stream.
Definition: berstream.hpp:32
bool readLength(unsigned int &length)
This reads an ASN.1 length from the BerStream.
A BerStream represents a BER-encoded stream of data.
Definition: berstream.hpp:16
bool writeType(uint8_t type)
This writes the given ASN.1 type to the buffer in BER.
bool copyTo(std::vector< char > &buffer)
TODO.
bool writeBytes(const char *buffer, unsigned int bufferSize, unsigned int &bytesWritten)
This writes the bytes given to the BerStream.
unsigned int remainingReadLength() const
This returns the number of bytes remaining in the stream.
unsigned int remainingWriteLength() const
This returns the number of bytes remaining in the stream.
bool peekType(uint8_t &type)
This reads an ASN.1 type from the BerStream.
bool writeLength(unsigned int encodedLength)
This writes the length to the buffer in BER.
Logger logger
We will expose a global Logger instance.
ByteStream * _byteStream
TODO.
Definition: berstream.hpp:135
unsigned int remainingWriteLength() const
This returns the number of bytes remaining in the stream.
Definition: berstream.hpp:38
bool read(typename EncodingClass::value_type &value)
This performs a full, logical read of a kind of encoded data.
Definition: berstream.hpp:145
Logging related to ByteStream.
Definition: logger.hpp:22
bool readType(uint8_t &type)
This reads an ASN.1 type from the BerStream.