From d30664e13f5045f384310007cfce9c365fb5ae2e Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 8 Nov 2012 21:18:35 -0500 Subject: [PATCH] added ssh test --- CMakeLists.txt | 1 + src/ssh.cpp | 136 +++++++++++++++++++++++++++++++++++++++++++++++-- tests/ssh.cpp | 23 +++++++++ 3 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 tests/ssh.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bc208f..bd1419a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ add_subdirectory(vendor/libssh2-1.4.2) setup_library( fc SOURCES ${sources} ) setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ) +setup_executable( ssh_test SOURCES tests/ssh.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} z) #add_executable( test_vec tests/vector_test.cpp ) #target_link_libraries( test_vec fc ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ) diff --git a/src/ssh.cpp b/src/ssh.cpp index 293957c..8881eb0 100644 --- a/src/ssh.cpp +++ b/src/ssh.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -19,15 +20,33 @@ namespace fc { namespace ssh { namespace detail { static int ssh_init = libssh2_init(0); + class process_istream : public fc::istream { + public: + virtual size_t readsome( char* buf, size_t len ) { return 0; } + virtual istream& read( char* buf, size_t len ) { return *this; } + + virtual bool eof()const { return true; } + }; + + class process_ostream : public fc::ostream { + public: + virtual ostream& write( const char* buf, size_t len ) { return *this; } + virtual void close(){} + virtual void flush(){} + }; + class process_impl : public fc::retainable { public: process_impl( const client& c ):sshc(c){} + process_istream std_err; + process_istream std_out; + process_ostream std_in; + client sshc; }; - class client_impl : public fc::retainable { public: LIBSSH2_SESSION* session; @@ -514,10 +533,121 @@ namespace fc { namespace ssh { return ft; } - void client::mkdir( const fc::path& remote_dir, int mode ) { + void client::mkdir( const fc::path& rdir, int mode ) { + auto s = stat(rdir); + if( s.is_directory() ) return; + else if( s.exists() ) { + FC_THROW_MSG( "Non directory exists at path %s", rdir.generic_string().c_str() ); + } + + int rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode ); + while( rc == LIBSSH2_ERROR_EAGAIN ) { + my->wait_on_socket(); + rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode ); + } + if( 0 != rc ) { + rc = libssh2_sftp_last_error(my->sftp); + FC_THROW_MSG( "mkdir error %s", rc ); + } } void client::close() { + if( my->session ) { + if( my->sftp ) { + int ec = libssh2_sftp_shutdown(my->sftp); + try { + while( ec == LIBSSH2_ERROR_EAGAIN ) { + my->wait_on_socket(); + ec = libssh2_sftp_shutdown(my->sftp); + } + }catch(...){ + elog( "... caught error closing sftp session???" ); + } + my->sftp = 0; + } + try { + int ec = libssh2_session_disconnect(my->session, "exit cleanly" ); + while( ec == LIBSSH2_ERROR_EAGAIN ) { + my->wait_on_socket(); + ec = libssh2_session_disconnect(my->session, "exit cleanly" ); + } + ec = libssh2_session_free(my->session); + while( ec == LIBSSH2_ERROR_EAGAIN ) { + my->wait_on_socket(); + ec = libssh2_session_free(my->session ); + } + my->session = 0; + } catch ( ... ){ + elog( "... caught error freeing session???" ); + my->session = 0; + } + try { + if( my->sock ) { + slog( "closing socket" ); + my->sock->close(); + } + } catch ( ... ){ + elog( "... caught error closing socket???" ); + } + my->sock.reset(0); + try { + if( my->read_prom ) my->read_prom->wait(); + } catch ( ... ){ + wlog( "caught error waiting on read prom" ); + } + try { + if( my->write_prom ) my->write_prom->wait(); + } catch ( ... ){ + wlog( "caught error waiting on write prom" ); + } + } + } + + file_attrib::file_attrib() + :size(0),uid(0),gid(0),permissions(0),atime(0),mtime(0) + { } + + bool file_attrib::is_directory() { + return LIBSSH2_SFTP_S_ISDIR(permissions); + } + bool file_attrib::is_file() { + return LIBSSH2_SFTP_S_ISREG(permissions); + } + bool file_attrib::exists() { + return 0 != permissions; + } + + + + + process::~process() + {} + + /** + * Blocks until the result code of the process has been returned. + */ + int process::result() { + return 0; + } + /** + * @brief returns a stream that writes to the procss' stdin + */ + fc::ostream& process::in_stream() { + return my->std_in; + } + /** + * @brief returns a stream that reads from the process' stdout + */ + fc::istream& process::out_stream() { + return my->std_out; + } + /** + * @brief returns a stream that reads from the process' stderr + */ + fc::istream& process::err_stream() { + return my->std_err; + } + process::process( client& c, const fc::string& cmd, const fc::string& pty_type) + { } - } } diff --git a/tests/ssh.cpp b/tests/ssh.cpp new file mode 100644 index 0000000..f434c0f --- /dev/null +++ b/tests/ssh.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +int main( int argc, char** argv ) { + try { + if( argc < 3 ) { + fc::cout<>pw; + fc::ssh::client c; + c.connect( "dlarimer", pw, "localhost" ); + c.scp_send( argv[1], argv[2] ); + } catch ( ... ) { + wlog( "%s", fc::except_str().c_str() ); + } + return 0; +}