RemoteSessionHandle

remotesessionhandle.h

#ifndef REMOTESESSIONHANDLE_H 
#define REMOTESESSIONHANDLE_H
 

#include "utils/asyncloop.h"
#include "utils/misc.h"
 

// AVOID ERROR BECAUSE OF swprintf
#undef __STRICT_ANSI__
 
// #define FOR WIN7. CAN'T FIND sdkddkver.h ON MINGW
#define _WIN32_WINNT 0x0601
#include <boost/asio.hpp>
#include <boost/function.hpp>
 

namespace ssh
{
 

class SessionHandle;
 

class RemoteSessionHandle
{
public:
    RemoteSessionHandle(boost::function<void(std::string)>& pReportStatus, 
        boost::asio::ip::tcp::socket& pSock, SessionHandle& pSessionHandle);
    ~RemoteSessionHandle();
 

    void CloseSession();
 

    // WE MAY ADD MOVE IN THE FUTURE, BUT NOT COPY
    RemoteSessionHandle(RemoteSessionHandle&&) = delete;
    RemoteSessionHandle& operator=(RemoteSessionHandle&&) = delete;
    RemoteSessionHandle(RemoteSessionHandle const&) = delete;
    RemoteSessionHandle& operator=(RemoteSessionHandle const&) = delete;
private:
    utils::TaskState DoHandshake();
    utils::TaskState DoCloseSession();
 

    utils::CleanupState cleanupState;
    boost::function<void(std::string)>& reportStatus;
    boost::asio::ip::tcp::socket& sock;
    SessionHandle& sessionHandle;
};
 

} // namespace ssh
#endif // REMOTESESSIONHANDLE_H


remotesessionhandle.cpp

#include "remotesessionhandle.h"
using utils::AsyncLoopTimer;
using utils::AsyncLoopSocket;
using boost::asio::io_service;
 

#include "sshexception.h"
#include "sessionhandle.h"
 

#include "libssh2_config.h"
#include <libssh2.h>
 

#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using boost::bind;
using boost::protect;
using boost::lexical_cast;
using boost::asio::deadline_timer;
using boost::posix_time::milliseconds;
 

#include <string>
using std::string;
 

namespace ssh
{

 
RemoteSessionHandle::RemoteSessionHandle( 
    boost::function<void(std::string)>& pReportStatus,
    boost::asio::ip::tcp::socket& pSock, SessionHandle& pSessionHandle) :
    cleanupState(utils::CleanupState::NoCleanup), 
    reportStatus(pReportStatus), sock(pSock), sessionHandle(pSessionHandle)
{
    if (!reportStatus.empty())
        reportStatus("SSH Handshake");
 
    io_service& ios = sock.get_io_service();
    ios.reset();
    sock.async_read_some(boost::asio::null_buffers(), bind(AsyncLoopSocket,
        protect(bind(&RemoteSessionHandle::DoHandshake, this)), 
        boost::ref(sock), true));
    ios.run();
}

RemoteSessionHandle::~RemoteSessionHandle()
{
    if (!reportStatus.empty())
        reportStatus("Cleanup: SSH remote session.");
 
    // WE'LL ONLY TRY TO CLEANUP IF NO ATTEMPT HAS BEEN MADE YET
    if (cleanupState == utils::CleanupState::NoCleanup)
    {
        try
        {
            CloseSession();
        }
        catch (...)
        { }
    }
}

void RemoteSessionHandle::CloseSession()
{
    io_service ios;
    deadline_timer dt(ios);
 
    dt.expires_from_now(milliseconds(10));
    dt.async_wait(bind(AsyncLoopTimer, 
        protect(bind(&RemoteSessionHandle::DoCloseSession, this)), 
        boost::ref(dt), 10));
 
    cleanupState = utils::CleanupState::CleanupInProgress;
    ios.run();
 
    cleanupState = utils::CleanupState::CleanupDone;
}


utils::TaskState RemoteSessionHandle::DoHandshake()
{
    int rc = libssh2_session_handshake(sessionHandle.GetSession(),  
        sock.native_handle());
 
    if (rc == LIBSSH2_ERROR_EAGAIN)
    {
        return utils::TASK_WORKING;
    }
 
    if (rc)
    {
        BOOST_THROW_EXCEPTION(SSHHandshakeError() <<
            ssh_error_string("Error " + lexical_cast<string>(rc) +  
            " during SSH Handshake.") << ssh_error_id(rc));
    }
 
    return utils::TASK_DONE;
}
 
utils::TaskState RemoteSessionHandle::DoCloseSession()
{
    int rc = libssh2_session_disconnect(sessionHandle.GetSession(),  
        "Disconnect SSH session");
 
    if (rc == LIBSSH2_ERROR_EAGAIN)
    {
        return utils::TASK_WORKING;
    }
 
    if (rc)
    {
        BOOST_THROW_EXCEPTION(SSHDisconnectSessionError() <<
            ssh_error_string("Error " + lexical_cast<string>(rc) +  
            " disconnecting SSH session.") << ssh_error_id(rc));
    }
 
    return utils::TASK_DONE;
}
 

} // namespace ssh
 







No comments:

Post a Comment