I have two classes
SslHandshake and
SslRequest with according to names functionality.
After client and server handshakes are done in the
SslHandshake, I pass both sockets to
SslRequest and start transferring data from server to client.
1. If I is not waiting for finishing of transferring, instance of
SslHandshake will be destroyed automatically (in the
~SslHandshake I will destroy both socket objects and transferring in the
SslRequest will be aborted).
2. If I start transferring with waiting, after a few iterations
SslRequest::ReadSocketOut will be called successfully, but the
readSocketHandle will not be called (so, will be called but with timeout error).
So, I need to handshake in one class and transfer data into another class.
How to prevent destroying instance of
SslHandshake until data transferring will be done into
SslRequest or how to fix socket reading without callback calling after a few iterations?
SslHandshake.h
class AsyncService : public boost::asio::io_service
{
public:
typedef boost::shared_ptr<AsyncService> SharedPtr;
public:
AsyncService(void);
public:
std::size_t ThreadHandle(void);
};
typedef AsyncService IoService;
typedef AsyncService::SharedPtr IoServicePtr;
#define IO_SERVICE_THREAD_VOID ThreadHandle
class SslHandshake
{
public:
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> StreamSsl;
public:
SslHandshake(IoService &service);
virtual ~SslHandshake(void);
private:
boost::asio::ssl::context *m_ContextIn;
boost::asio::ssl::context *m_ContextOut;
StreamSsl *m_SocketIn;
StreamSsl *m_SocketOut;
private:
void HandshakeInHandle(const boost::system::error_code &error);
};
SslHandshake.cpp
AsyncService::AsyncService(void)
{
}
std::size_t AsyncService::ThreadHandle(void)
{
std::size_t result = 0;
TRY
{
result = run();
}
CATCH_LOG_STD
CATCH_LOG_ANY
return result;
}
#define SHARED_FROM_THIS boost::static_pointer_cast<SslHandshake>(shared_from_this())
SslHandshake::SslHandshake(IoService &service)
{
m_ContextIn = new baSSL::context(service, baSSL::context::sslv23);
m_ContextIn->set_options(
baSSL::context::default_workarounds |
baSSL::context::no_sslv2 |
baSSL::context::single_dh_use);
m_ContextIn->set_password_callback(
boost::bind(
&SslHandshake::GetPasswordInHandle,
this));
m_ContextIn->use_certificate_chain_file("server.crt");
m_ContextIn->use_private_key_file("server.key", baSSL::context::pem);
m_ContextIn->use_tmp_dh_file("dh512.pem");
m_ContextOut = new baSSL::context(baSSL::context::sslv23);
m_SocketIn = new StreamSsl(service, *m_ContextIn);
m_SocketOut = new StreamSsl(service, *m_ContextOut);
m_SocketOut->set_verify_mode(baSSL::verify_peer);
m_SocketOut->set_verify_callback(
boost::bind(
&SslHandshake::VerifyCertificateOutHandle,
this,
_1,
_2));
}
SslHandshake::~SslHandshake(void)
{
Release(ProxySocket::Both);
DELETE_CHECK(m_SocketOut);
DELETE_CHECK(m_SocketIn);
DELETE_CHECK(m_ContextOut);
DELETE_CHECK(m_ContextIn);
}
void SslHandshake::HandshakeInHandle(const bSystem::error_code &error)
{
TRY
{
CHECK_BOOST_ERROR
{
LOG_MSG_DEBUG_KEYWORD(KEYWORD_INCOMING, << "Handshake done");
SslRequest::SocketPtr socketIn(m_SocketIn);
SslRequest::SocketPtr socketOut(m_SocketOut);
IoServicePtr servicePointer((IoService *)&m_SocketIn->get_io_service());
servicePointer->SessionIndex = IndexThis;
SslRequest::SharedPtr request = SslRequest::CreateInstance(socketIn, socketOut INDEX_THIS_PASS);
request->Transfer();
servicePointer->IO_SERVICE_THREAD_VOID();
}
}
CATCH_LOG_STD
CATCH_LOG_ANY
}
SslRequest.h
class SslRequest
{
protected:
typedef std::vector<char> TransferringBuffer;
enum ProxySocket
{
In = BOOST_BINARY(01),
Out = BOOST_BINARY(10),
Both = In | Out
};
public:
typedef boost::shared_ptr<SslRequest> SharedPtr;
typedef boost::shared_ptr<SslHandshake::StreamSsl> SocketPtr;
public:
SslRequest(SocketPtr socketIn, SocketPtr socketOut);
virtual ~SslRequest(void);
private:
SocketPtr m_SocketIn;
SocketPtr m_SocketOut;
boost::mutex m_Mutex;
boost::mutex::scoped_lock *m_Lock;
boost::condition_variable m_Condition;
public:
void Transfer(void);
private:
virtual void ReadSocketOut(TransferringBuffer &buffer, SimpleSocketCallback readSocketHandle);
virtual void Release(const ProxySocket what);
};
SslRequest.cpp
#define SHARED_FROM_THIS boost::static_pointer_cast<SslRequest>(shared_from_this())
SslRequest::SslRequest(SocketPtr socketIn, SocketPtr socketOut)
{
LOG_FUNC_START;
m_SocketIn = socketIn;
m_SocketOut = socketOut;
}
SslRequest::~SslRequest(void)
{
Release(ProxySocket::Both);
DELETE_CHECK(m_Lock);
}
void SslRequest::Transfer(void)
{
ReceiveHeadersIn();
}
void SslRequest::ReadSocketOut(TransferringBuffer &buffer, SimpleSocketCallback readSocketHandle)
{
bAsIO::async_read(
*m_SocketOut,
bAsIO::buffer(buffer),
boost::bind(
readSocketHandle,
SHARED_FROM_THIS,
baPlaceholders::error,
baPlaceholders::bytes_transferred));
}