IBR-DTNSuite  0.8
ibrcommon/ibrcommon/ssl/CipherStream.cpp
Go to the documentation of this file.
00001 /*
00002  * CipherStream.cpp
00003  *
00004  *  Created on: 13.07.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/ssl/CipherStream.h"
00009 
00010 namespace ibrcommon
00011 {
00012         CipherStream::CipherStream(std::ostream &stream, const CipherMode mode, const size_t buffer)
00013          : std::ostream(this), _stream(stream), _mode(mode), data_buf_(new char[buffer]), data_size_(buffer)
00014         {
00015                 setp(data_buf_, data_buf_ + data_size_ - 1);
00016         }
00017 
00018         CipherStream::~CipherStream()
00019         {
00020                 delete[] data_buf_;
00021         }
00022 
00023         void CipherStream::encrypt(std::iostream& stream)
00024         {
00025                 char buf[4096];
00026                 while (!stream.eof())
00027                 {
00028                         std::ios::pos_type pos = stream.tellg();
00029 
00030                         stream.read((char*)&buf, 4096);
00031                         size_t bytes = stream.gcount();
00032 
00033                         encrypt(buf, bytes);
00034 
00035                         // clear the error flags if we reached the end of the file
00036                         // but need to write some data
00037                         if (stream.eof() && (bytes > 0)) stream.clear();
00038 
00039                         stream.seekp(pos, std::ios::beg);
00040                         stream.write((char*)&buf, bytes);
00041                 }
00042 
00043                 stream.flush();
00044                 encrypt_final();
00045         }
00046 
00047         void CipherStream::decrypt(std::iostream& stream)
00048         {
00049                 char buf[4096];
00050                 while (!stream.eof())
00051                 {
00052                         std::ios::pos_type pos = stream.tellg();
00053 
00054                         stream.read((char*)&buf, 4096);
00055                         size_t bytes = stream.gcount();
00056 
00057                         decrypt(buf, bytes);
00058 
00059                         // clear the error flags if we reached the end of the file
00060                         // but need to write some data
00061                         if (stream.eof() && (bytes > 0)) stream.clear();
00062 
00063                         stream.seekp(pos, std::ios::beg);
00064                         stream.write((char*)&buf, bytes);
00065                 }
00066 
00067                 stream.flush();
00068                 decrypt_final();
00069         }
00070 
00071         int CipherStream::sync()
00072         {
00073                 int ret = std::char_traits<char>::eq_int_type(this->overflow(
00074                                 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
00075                                 : 0;
00076 
00077                 // do cipher stuff
00078                 switch (_mode)
00079                 {
00080                 case CIPHER_ENCRYPT:
00081                         encrypt_final();
00082                         break;
00083 
00084                 case CIPHER_DECRYPT:
00085                         decrypt_final();
00086                         break;
00087                 }
00088 
00089                 return ret;
00090         }
00091 
00092         std::char_traits<char>::int_type CipherStream::overflow(std::char_traits<char>::int_type c)
00093         {
00094                 char *ibegin = data_buf_;
00095                 char *iend = pptr();
00096 
00097                 // mark the buffer as free
00098                 setp(data_buf_, data_buf_ + data_size_ - 1);
00099 
00100                 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
00101                 {
00102                         *iend++ = std::char_traits<char>::to_char_type(c);
00103                 }
00104 
00105                 // if there is nothing to send, just return
00106                 if ((iend - ibegin) == 0)
00107                 {
00108                         return std::char_traits<char>::not_eof(c);
00109                 }
00110 
00111                 // do cipher stuff
00112                 switch (_mode)
00113                 {
00114                 case CIPHER_ENCRYPT:
00115                         encrypt(data_buf_, (iend - ibegin));
00116                         break;
00117 
00118                 case CIPHER_DECRYPT:
00119                         decrypt(data_buf_, (iend - ibegin));
00120                         break;
00121                 }
00122 
00123                 // write result to stream
00124                 _stream.write(data_buf_, (iend - ibegin));
00125 
00126                 return std::char_traits<char>::not_eof(c);
00127         }
00128 }