Click here to Skip to main content
15,885,546 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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
C++
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
C++
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");

            // --- Transfer with waiting of mutex
            //IoServicePtr servicePointer((IoService *)&m_SocketIn->get_io_service());
            //boost::thread serviceThread(boost::bind(&IoService::IO_SERVICE_THREAD_VOID, servicePointer));
            //SslRequest::SharedPtr sslRequest(new SslRequest(m_SocketIn, m_SocketOut));
            //sslRequest->Transfer();

            SslRequest::SocketPtr socketIn(m_SocketIn);
            SslRequest::SocketPtr socketOut(m_SocketOut);

            // --- Transfer with waiting of thread
            //IoServicePtr servicePointer((IoService *)&m_SocketIn->get_io_service());
            //servicePointer->SessionIndex = IndexThis;
            //boost::thread serviceThread(boost::bind(&IoService::IO_SERVICE_THREAD_VOID, servicePointer));
            //SslRequest::SharedPtr request = SslRequest::CreateInstance(m_SocketIn, m_SocketOut);
            //request->Transfer();
            //serviceThread.join();

            // --- Transfer with waiting of IO_SERVICE_THREAD_VOID
            IoServicePtr servicePointer((IoService *)&m_SocketIn->get_io_service());
            servicePointer->SessionIndex = IndexThis;
            SslRequest::SharedPtr request = SslRequest::CreateInstance(/*m_SocketIn, m_SocketOut*/socketIn, socketOut INDEX_THIS_PASS);
            request->Transfer();
            servicePointer->IO_SERVICE_THREAD_VOID();
        }
    }
    CATCH_LOG_STD
    CATCH_LOG_ANY
}


SslRequest.h
C++
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(/*SslHandshake::StreamSsl *socketIn, SslHandshake::StreamSsl *socketOut*/SocketPtr socketIn, SocketPtr socketOut);
    virtual ~SslRequest(void);

private:
    /*SslHandshake::StreamSsl *m_SocketIn;
    SslHandshake::StreamSsl *m_SocketOut;*/
    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
C++
#define SHARED_FROM_THIS boost::static_pointer_cast<SslRequest>(shared_from_this())

SslRequest::SslRequest(/*SslHandshake::StreamSsl *socketIn, SslHandshake::StreamSsl *socketOut*/SocketPtr socketIn, SocketPtr socketOut)
{
    LOG_FUNC_START;

    m_SocketIn = socketIn;
    m_SocketOut = socketOut;
    //m_SocketIn = std::move(socketIn);
    //m_SocketOut = std::move(socketOut);

    // For transferring with waiting of mutex
    //m_Lock = new boost::mutex::scoped_lock(m_Mutex);
}

SslRequest::~SslRequest(void)
{
    Release(ProxySocket::Both);
    DELETE_CHECK(m_Lock);
}

void SslRequest::Transfer(void)
{
    ReceiveHeadersIn();

    // For transferring with waiting of mutex
    //m_Condition.wait(*m_Lock);
}

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));
}
Posted

1 solution

For resources that should be shared between other objects and automatically deleted when the last object using that resource is destroyed you use a shared_ptr. If you're using a C++98 compiler then use the implementation from boost or tr1, otherwise use the standard one.

You could simplify a lot more of your code using unique_ptr - you'll get rid of most of the manual memory management if you do that.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900