merge latest changes
This commit is contained in:
commit
7b9a14918c
21 changed files with 204 additions and 117 deletions
|
|
@ -109,7 +109,7 @@ add_subdirectory(vendor)
|
|||
setup_library( fc SOURCES ${sources} )
|
||||
|
||||
#setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${ZLIB_LIBRARY} ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_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} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_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} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
|
||||
|
||||
setup_executable( logger_test SOURCES tests/logger.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} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ namespace fc {
|
|||
struct lexical_cast<fc::string, R> {
|
||||
static fc::string cast( const R& v ) { return to_string( v ); }
|
||||
};
|
||||
template<typename R>
|
||||
struct lexical_cast<std::string, R> {
|
||||
static std::string cast( const R& v ) { return to_string( v ); }
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct lexical_cast<uint64_t, R> {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ namespace fc {
|
|||
ovalue meta;
|
||||
|
||||
// key based args
|
||||
template<typename T>
|
||||
log_message& operator()( const string& arg, const T& v ) {
|
||||
return (*this)(arg,value(v));
|
||||
}
|
||||
|
||||
log_message& operator()( const string& arg, value&& v );
|
||||
log_message& operator()( const string& arg, const value& v );
|
||||
// position based args...
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
//#include <fc/function.hpp>
|
||||
#include <fc/future.hpp>
|
||||
#include <functional>
|
||||
#include <boost/config.hpp>
|
||||
|
|
|
|||
|
|
@ -75,9 +75,11 @@ void throw_bad_enum_cast( const char* k, const char* e );
|
|||
fc::reflector<base>::visit( visitor );
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef _MSC_VER
|
||||
#define TEMPLATE template
|
||||
#else
|
||||
// Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name
|
||||
#pragma warning( disable: 4482 )
|
||||
#define TEMPLATE
|
||||
#endif
|
||||
|
||||
|
|
@ -178,6 +180,11 @@ template<> struct reflector<TYPE> {\
|
|||
#define FC_REFLECT( TYPE, MEMBERS ) \
|
||||
FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
|
||||
#define FC_REFLECT_TYPENAME( TYPE ) \
|
||||
namespace fc { \
|
||||
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
|
||||
}
|
||||
|
||||
#define FC_REFLECT_FWD( TYPE ) \
|
||||
namespace fc { \
|
||||
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace fc {
|
||||
class path;
|
||||
class logger;
|
||||
namespace ssh {
|
||||
namespace detail {
|
||||
class client_impl;
|
||||
|
|
@ -56,9 +57,37 @@ namespace fc {
|
|||
* Because the client creates other resources that depend upon
|
||||
* it, it can only be created as a std::shared_ptr<client> (aka client::ptr)
|
||||
* via client::create();
|
||||
*
|
||||
*/
|
||||
class client {
|
||||
public:
|
||||
enum trace_level {
|
||||
TRACE_NONE = 0,
|
||||
TRACE_TRANS = (1<<1),
|
||||
TRACE_KEX = (1<<2),
|
||||
TRACE_AUTH = (1<<3),
|
||||
TRACE_CONN = (1<<4),
|
||||
TRACE_SCP = (1<<5),
|
||||
TRACE_SFTP = (1<<6),
|
||||
TRACE_ERROR = (1<<7),
|
||||
TRACE_PUBLICKEY = (1<<8),
|
||||
TRACE_SOCKET = (1<<9)
|
||||
};
|
||||
/**
|
||||
* Everything but TRACE_ERROR will be logged at fc::log_level::debug, while
|
||||
* TRACE_ERROR will be logged at fc::log_level::error
|
||||
*
|
||||
* @param bitmask comprised of values from trace_level
|
||||
**/
|
||||
void set_trace_level( int bitmask );
|
||||
int get_trace_level()const;
|
||||
|
||||
/**
|
||||
* Override the default logger used by fc::ssh::client
|
||||
*/
|
||||
void set_logger( const logger& lgr );
|
||||
const logger& get_logger()const;
|
||||
|
||||
void connect( const fc::string& user, const fc::string& host, uint16_t port = 22);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ namespace std {
|
|||
typedef basic_string<char, char_traits<char>, allocator<char> > string;
|
||||
}
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace fc {
|
||||
// typedef std::string string;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ namespace fc {
|
|||
typedef fc::tuple<BOOST_PP_ENUM( n, DEDUCE_MEMBERS,unused)> type; \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, 4, TUPLE, unused )
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, 5, TUPLE, unused )
|
||||
|
||||
|
||||
#undef FORWARD_PARAMS
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
#ifndef _FC_UTILITY_HPP_
|
||||
#define _FC_UTILITY_HPP_
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <new>
|
||||
|
||||
#define nullptr 0
|
||||
//#define nullptr 0
|
||||
|
||||
typedef decltype(sizeof(int)) size_t;
|
||||
namespace std {
|
||||
|
|
@ -49,4 +48,3 @@ namespace fc {
|
|||
a = fc::move(b);
|
||||
b = fc::move(tmp);
|
||||
}
|
||||
#endif // _FC_UTILITY_HPP_
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
#include <fc/optional.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name
|
||||
#pragma warning( disable: 4482 )
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
template<BOOST_PP_ENUM_PARAMS(9, typename A)> struct tuple;
|
||||
|
||||
|
|
|
|||
|
|
@ -277,6 +277,9 @@ namespace fc {
|
|||
}
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
inline void unpack( const fc::value& val, tuple<A,B,C,D>& t ) {
|
||||
if( val.size() < tuple<A,B,C,D>::size )
|
||||
FC_THROW_REPORT( "Attempt to unpack tuple of size ${size} from array of size ${array_size}",
|
||||
fc::value( "size", tuple<A,B,C,D>::size)("array_size",val.size() ) );
|
||||
t.visit( tuple_from_value_visitor(val) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace fc {
|
|||
}
|
||||
|
||||
fc::string path::string()const {
|
||||
return _p->string().c_str();
|
||||
return _p->string();
|
||||
}
|
||||
fc::path path::filename()const {
|
||||
return _p->filename();
|
||||
|
|
|
|||
|
|
@ -120,9 +120,9 @@ namespace fc { namespace json {
|
|||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
FC_THROW_MSG( "Unexpected reply with id %s", id );
|
||||
FC_THROW_REPORT( "Unexpected reply with id ${id}", id_itr->val );
|
||||
}
|
||||
FC_THROW_MSG( "Method with no 'id' or 'method' field" );
|
||||
FC_THROW_REPORT( "Method with no 'id' or 'method' field" );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,19 +38,18 @@ namespace fc { namespace json {
|
|||
fc::string line;
|
||||
fc::getline( in, line );
|
||||
while( !in.eof() ) {
|
||||
// std::cerr<<"\n**line size: "<<line.size()<<"\n\n";
|
||||
// slog( "line size: '%d'", line.size() );
|
||||
// slog( "%s", line.c_str() );
|
||||
try {
|
||||
fc_dlog( log, "Received: '${line}'", ("line",line) );
|
||||
fc::value v= fc::json::from_string( line );
|
||||
self.handle_message(v);
|
||||
} catch ( fc::error_report& er ) {
|
||||
fc_wlog( log, "Error handling request '${line}'\n ${report}", ("line",line)("report",er.to_detail_string() ) );
|
||||
} catch (...) {
|
||||
fc_wlog( log, "Error handling request '${exception}'",("exception",fc::except_str()) );
|
||||
return;
|
||||
}
|
||||
fc::async( [=]() {
|
||||
try {
|
||||
fc_dlog( log, "Received: '${line}'", ("line",line) );
|
||||
fc::value v= fc::json::from_string( line );
|
||||
self.handle_message(v);
|
||||
} catch ( fc::error_report& er ) {
|
||||
fc_wlog( log, "Error handling request '${line}'\n ${report}", ("line",line)("report",er.to_detail_string() ) );
|
||||
} catch (...) {
|
||||
fc_wlog( log, "Error handling request '${exception}'",("exception",fc::except_str()) );
|
||||
return;
|
||||
}
|
||||
});
|
||||
fc::getline( in, line );
|
||||
}
|
||||
} catch ( ... ) {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ namespace fc {
|
|||
}
|
||||
|
||||
void logger::log( log_message m ) {
|
||||
m.context = my->_name;
|
||||
if( !m.context ) m.context = my->_name;
|
||||
else m.context = *m.context + "->" + my->_name;
|
||||
for( auto itr = my->_appenders.begin(); itr != my->_appenders.end(); ++itr )
|
||||
(*itr)->log( m );
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace fc {
|
|||
get_logger_map().clear();
|
||||
get_appender_map().clear();
|
||||
|
||||
slog( "\n%s", fc::json::to_pretty_string(cfg).c_str() );
|
||||
//slog( "\n%s", fc::json::to_pretty_string(cfg).c_str() );
|
||||
for( size_t i = 0; i < cfg.appenders.size(); ++i ) {
|
||||
appender::create( cfg.appenders[i].name, cfg.appenders[i].type, cfg.appenders[i].args );
|
||||
// TODO... process enabled
|
||||
|
|
@ -48,7 +48,7 @@ namespace fc {
|
|||
}
|
||||
|
||||
logging_config logging_config::default_config() {
|
||||
slog( "default cfg" );
|
||||
//slog( "default cfg" );
|
||||
logging_config cfg;
|
||||
cfg.appenders.push_back(
|
||||
appender_config( "stderr", "console",
|
||||
|
|
|
|||
170
src/ssh.cpp
170
src/ssh.cpp
|
|
@ -12,7 +12,10 @@
|
|||
#include <fc/unique_lock.hpp>
|
||||
#include <fc/mutex.hpp>
|
||||
#include <fc/ip.hpp>
|
||||
#include <fc/spin_lock.hpp>
|
||||
#include <fc/scoped_lock.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <fc/logger.hpp>
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
#include <memory>
|
||||
|
|
@ -76,10 +79,13 @@ namespace fc { namespace ssh {
|
|||
class client_impl : public fc::retainable {
|
||||
public:
|
||||
client_impl() {
|
||||
sftp = nullptr;
|
||||
session = nullptr;
|
||||
knownhosts = nullptr;
|
||||
}
|
||||
sftp = nullptr;
|
||||
session = nullptr;
|
||||
knownhosts = nullptr;
|
||||
_trace_level = LIBSSH2_TRACE_ERROR;
|
||||
logr = fc::logger::get( "fc::ssh::client" );
|
||||
logr.set_parent( fc::logger::get( "default" ) );
|
||||
}
|
||||
LIBSSH2_SESSION* session;
|
||||
LIBSSH2_KNOWNHOSTS* knownhosts;
|
||||
LIBSSH2_SFTP* sftp;
|
||||
|
|
@ -98,6 +104,7 @@ namespace fc { namespace ssh {
|
|||
bool session_connected;
|
||||
fc::promise<boost::system::error_code>::ptr read_prom;
|
||||
fc::promise<boost::system::error_code>::ptr write_prom;
|
||||
fc::spin_lock _spin_lock;
|
||||
|
||||
LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type );
|
||||
static void kbd_callback(const char *name, int name_len,
|
||||
|
|
@ -166,26 +173,30 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) );
|
||||
|
||||
bool resolved = false;
|
||||
bool resolved = false;
|
||||
for( uint32_t i = 0; i < eps.size(); ++i ) {
|
||||
std::stringstream ss; ss << eps[i];
|
||||
try {
|
||||
boost::system::error_code ec;
|
||||
std::stringstream ss; ss << eps[i];
|
||||
slog( "Attempting to connect to %s", ss.str().c_str() );
|
||||
fc::asio::tcp::connect( *sock, eps[i] );
|
||||
endpt = eps[i];
|
||||
resolved = true;
|
||||
break;
|
||||
} catch ( ... ) {
|
||||
wlog( "%s", fc::except_str().c_str() );
|
||||
sock->close();
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
fc_ilog( logr, "Attempting to connect to ${endpoint}", ("endpoint",ss.str().c_str()) );
|
||||
fc::asio::tcp::connect( *sock, eps[i] );
|
||||
endpt = eps[i];
|
||||
resolved = true;
|
||||
break;
|
||||
} catch ( fc::error_report& er ) {
|
||||
fc_ilog( logr, "Failed to connect to ${endpoint}\n${error_reprot}",
|
||||
("endpoint",ss.str().c_str())("error_report", er.to_detail_string()) );
|
||||
sock->close();
|
||||
}
|
||||
}
|
||||
if( !resolved ) {
|
||||
FC_THROW_REPORT( "Unable to connect to any resolved endpoint for ${host}:${port}",
|
||||
fc::value().set("host", hostname).set("port",port) );
|
||||
}
|
||||
if( !resolved ) {
|
||||
FC_THROW_REPORT( "Unable to connect to any resolved endpoint for ${host}:${port}",
|
||||
fc::value().set("host", hostname).set("port",port) );
|
||||
}
|
||||
session = libssh2_session_init();
|
||||
libssh2_trace( session, _trace_level );
|
||||
libssh2_trace_sethandler( session, this, client_impl::handle_trace );
|
||||
|
||||
*libssh2_session_abstract(session) = this;
|
||||
|
||||
libssh2_session_set_blocking( session, 0 );
|
||||
|
|
@ -207,14 +218,21 @@ namespace fc { namespace ssh {
|
|||
authenticate();
|
||||
//slog(".");
|
||||
} catch ( error_report& er ) {
|
||||
elog( "%s", er.to_detail_string().c_str() );
|
||||
elog( "%s", er.to_detail_string().c_str() );
|
||||
close();
|
||||
throw FC_REPORT_PUSH( er, "Unable to connect to ssh server" );;
|
||||
} catch ( ... ) {
|
||||
close();
|
||||
FC_THROW_REPORT( "Unable to connect to ssh server", fc::value().set("exception", fc::except_str() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ) {
|
||||
client_impl* my = (client_impl*)context;
|
||||
fc::string str(data,length);
|
||||
fc_wlog( my->logr, "${message}", ("message",str) );
|
||||
}
|
||||
|
||||
|
||||
void close() {
|
||||
if( session ) {
|
||||
|
|
@ -226,7 +244,7 @@ namespace fc { namespace ssh {
|
|||
ec = libssh2_sftp_shutdown(sftp);
|
||||
}
|
||||
}catch(...){
|
||||
elog( "... caught error closing sftp session???" );
|
||||
fc_wlog( logr, "caught closing sftp session" );
|
||||
}
|
||||
sftp = 0;
|
||||
}
|
||||
|
|
@ -243,33 +261,31 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
session = 0;
|
||||
} catch ( ... ){
|
||||
elog( "... caught error freeing session???" );
|
||||
fc_wlog( logr, "caught freeing session" );
|
||||
session = 0;
|
||||
}
|
||||
try {
|
||||
if( sock ) {
|
||||
slog( "closing socket" );
|
||||
sock->close();
|
||||
}
|
||||
} catch ( ... ){
|
||||
elog( "... caught error closing socket???" );
|
||||
fc_wlog( logr, "caught error closing socket" );
|
||||
}
|
||||
sock.reset(0);
|
||||
try {
|
||||
if( read_prom ) read_prom->wait();
|
||||
} catch ( ... ){
|
||||
wlog( "caught error waiting on read prom" );
|
||||
fc_wlog( logr, "caught error waiting on read" );
|
||||
}
|
||||
try {
|
||||
if( write_prom ) write_prom->wait();
|
||||
} catch ( ... ){
|
||||
wlog( "caught error waiting on write prom" );
|
||||
fc_wlog( logr, "caught error waiting on write" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void authenticate() {
|
||||
//slog( "auth" );
|
||||
try {
|
||||
char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size());
|
||||
char * msg = 0;
|
||||
|
|
@ -308,7 +324,7 @@ namespace fc { namespace ssh {
|
|||
keybd = true;
|
||||
}
|
||||
else {
|
||||
slog( "Unknown/unsupported authentication type '%s'", s.c_str() );
|
||||
fc_wlog( logr, "Unknown/unsupported authentication type '${auth_type}'", ("auth_type",s.c_str()));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -331,7 +347,6 @@ namespace fc { namespace ssh {
|
|||
} // authenticate()
|
||||
|
||||
bool try_pass() {
|
||||
//slog( "try pass" );
|
||||
int ec = libssh2_userauth_password(session, uname.c_str(), upass.c_str() );
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
wait_on_socket();
|
||||
|
|
@ -341,7 +356,6 @@ namespace fc { namespace ssh {
|
|||
return !ec;
|
||||
}
|
||||
bool try_keyboard() {
|
||||
//slog( "try keyboard" );
|
||||
int ec = libssh2_userauth_keyboard_interactive(session, uname.c_str(),
|
||||
&client_impl::kbd_callback);
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
|
|
@ -353,7 +367,6 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
|
||||
bool try_pub_key() {
|
||||
//slog( "try pub key" );
|
||||
int ec = libssh2_userauth_publickey_fromfile(session,
|
||||
uname.c_str(),
|
||||
pubkey.c_str(),
|
||||
|
|
@ -375,7 +388,7 @@ namespace fc { namespace ssh {
|
|||
* @todo figure out why this method results in deadlocks...
|
||||
*/
|
||||
void wait_on_socket() {
|
||||
fc::usleep( fc::microseconds(10000) );
|
||||
fc::usleep(fc::microseconds(5000));
|
||||
return;
|
||||
|
||||
auto dir = libssh2_session_block_directions(session);
|
||||
|
|
@ -383,53 +396,52 @@ namespace fc { namespace ssh {
|
|||
|
||||
fc::promise<boost::system::error_code>::ptr rprom, wprom;
|
||||
if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) {
|
||||
rprom = read_prom;
|
||||
if(!rprom.get()) {
|
||||
// elog( " this %2% NEW READ PROM %1% ", read_prom.get(), this );
|
||||
read_prom.reset( new fc::promise<boost::system::error_code>("read_prom") );
|
||||
// wlog( " new read prom %1% this %2%", read_prom.get(), this );
|
||||
rprom = read_prom;
|
||||
sock->async_read_some( boost::asio::null_buffers(),
|
||||
[=]( const boost::system::error_code& e, size_t ) {
|
||||
this->read_prom->set_value(e);
|
||||
this->read_prom.reset(0);
|
||||
} );
|
||||
} else {
|
||||
// elog( "already waiting on read %1%", read_prom.get() );
|
||||
fc::scoped_lock<fc::spin_lock> lock(this->_spin_lock);
|
||||
if( !read_prom ) {
|
||||
read_prom.reset( new fc::promise<boost::system::error_code>("read_prom") );
|
||||
sock->async_read_some( boost::asio::null_buffers(),
|
||||
[=]( const boost::system::error_code& e, size_t ) {
|
||||
fc::scoped_lock<fc::spin_lock> lock(this->_spin_lock);
|
||||
this->read_prom->set_value(e);
|
||||
this->read_prom.reset(nullptr);
|
||||
} );
|
||||
}
|
||||
rprom = read_prom;
|
||||
}
|
||||
|
||||
if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) {
|
||||
wprom = write_prom;
|
||||
fc::scoped_lock<fc::spin_lock> lock(this->_spin_lock);
|
||||
if( !write_prom ) {
|
||||
write_prom.reset( new fc::promise<boost::system::error_code>("write_prom") );
|
||||
wprom = write_prom;
|
||||
sock->async_write_some( boost::asio::null_buffers(),
|
||||
[=]( const boost::system::error_code& e, size_t ) {
|
||||
this->write_prom->set_value(e);
|
||||
this->write_prom.reset(0);
|
||||
} );
|
||||
} else {
|
||||
// elog( "already waiting on write" );
|
||||
}
|
||||
wprom = write_prom;
|
||||
}
|
||||
|
||||
|
||||
boost::system::error_code ec;
|
||||
if( rprom.get() && wprom.get() ) {
|
||||
// elog( "************* Attempt to wait in either direction currently waits for both directions ****** " );
|
||||
//wlog( "rprom %1% wprom %2%", rprom.get(), write_prom.get() );
|
||||
// wlog( "wait on read %1% or write %2% ", rprom.get(), wprom.get() );
|
||||
wlog( "wait both dir" );
|
||||
|
||||
typedef fc::future<boost::system::error_code> fprom;
|
||||
fprom fw(wprom);
|
||||
fprom fr(rprom);
|
||||
int r = fc::wait_any( fw, fr, fc::seconds(5) );
|
||||
int r = fc::wait_any( fw, fr, fc::seconds(1) );
|
||||
switch( r ) {
|
||||
case 0:
|
||||
if( wprom->wait() ) {
|
||||
FC_THROW_REPORT( "Socket Error ${message}",
|
||||
fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) );
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if( rprom->wait() ) {
|
||||
FC_THROW_REPORT( "Socket Error ${message}",
|
||||
fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if( rprom ) {
|
||||
|
|
@ -444,6 +456,7 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_sftp() {
|
||||
if( !sftp ) {
|
||||
sftp = libssh2_sftp_init(session);
|
||||
|
|
@ -460,13 +473,20 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int _trace_level;
|
||||
logger logr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
client::client():my( new detail::client_impl() ){}
|
||||
client::~client(){}
|
||||
|
||||
void client::set_trace_level( int bitmask ) { my->_trace_level = bitmask; }
|
||||
int client::get_trace_level()const { return my->_trace_level; }
|
||||
const logger& client::get_logger()const { return my->logr; }
|
||||
void client::set_logger( const logger& l ) { my->logr = l; }
|
||||
|
||||
void client::connect( const fc::string& user, const fc::string& host, uint16_t port ) {
|
||||
my->hostname = host;
|
||||
my->uname = user;
|
||||
|
|
@ -498,7 +518,7 @@ namespace fc { namespace ssh {
|
|||
if( remote_dir.filename() == fc::path(".") )
|
||||
remote_dir /= local_dir.filename();
|
||||
|
||||
slog( "scp -r %s %s", local_dir.generic_string().c_str(), remote_dir.generic_string().c_str() );
|
||||
fc_dlog( my->logr, "scp -r ${local} ${remote}", ("local",local_dir)("remote",remote_dir) );
|
||||
create_directories( remote_dir );
|
||||
|
||||
directory_iterator ditr(local_dir);
|
||||
|
|
@ -514,7 +534,7 @@ namespace fc { namespace ssh {
|
|||
} else if( fc::is_regular_file(*ditr) ) {
|
||||
scp_send( *ditr, remote_dir / (*ditr).filename() );
|
||||
} else {
|
||||
wlog( "Skipping %s", fc::canonical(*ditr).generic_string().c_str() );
|
||||
fc_wlog( my->logr, "Skipping '${path}", ("path",fc::canonical(*ditr)) );
|
||||
}
|
||||
++ditr;
|
||||
}
|
||||
|
|
@ -522,7 +542,7 @@ namespace fc { namespace ssh {
|
|||
|
||||
void client::scp_send( const fc::path& local_path, const fc::path& remote_path,
|
||||
std::function<bool(size_t,size_t)> progress ) {
|
||||
slog( "scp %s %s", local_path.generic_string().c_str(), remote_path.generic_string().c_str() );
|
||||
fc_ilog( my->logr, "scp ${local} ${remote}", ("local",local_path)("remote",remote_path ) );
|
||||
/**
|
||||
* Tests have shown that if one scp is 'blocked' by a need to read (presumably to
|
||||
* ack recv for the trx window), and then a second transfer begins that the first
|
||||
|
|
@ -606,7 +626,6 @@ namespace fc { namespace ssh {
|
|||
ec = libssh2_channel_close( chan );
|
||||
}
|
||||
} catch ( error_report& er ) {
|
||||
wlog( "%s", er.to_detail_string().c_str() );
|
||||
// clean up chan
|
||||
int ec = libssh2_channel_free(chan );
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
|
|
@ -715,7 +734,7 @@ namespace fc { namespace ssh {
|
|||
ec = libssh2_sftp_shutdown(my->sftp);
|
||||
}
|
||||
}catch(...){
|
||||
elog( "... caught error closing sftp session???" );
|
||||
fc_wlog( my->logr, "caught closing sftp sessionn" );
|
||||
}
|
||||
my->sftp = 0;
|
||||
}
|
||||
|
|
@ -732,27 +751,26 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
my->session = 0;
|
||||
} catch ( ... ){
|
||||
elog( "... caught error freeing session???" );
|
||||
fc_wlog( my->logr, "caught error freeing session" );
|
||||
my->session = 0;
|
||||
}
|
||||
try {
|
||||
if( my->sock ) {
|
||||
slog( "closing socket" );
|
||||
my->sock->close();
|
||||
}
|
||||
} catch ( ... ){
|
||||
elog( "... caught error closing socket???" );
|
||||
fc_wlog( my->logr, "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" );
|
||||
fc_wlog( my->logr,"caught error waiting on read prom" );
|
||||
}
|
||||
try {
|
||||
if( my->write_prom ) my->write_prom->wait();
|
||||
} catch ( ... ){
|
||||
wlog( "caught error waiting on write prom" );
|
||||
fc_wlog( my->logr, "caught error waiting on write prom" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -837,19 +855,22 @@ namespace fc { namespace ssh {
|
|||
|
||||
void detail::process_impl::flush() {
|
||||
if( !chan ) return;
|
||||
/* channel_flush deleates input buffer, and does not ensure writes go out
|
||||
*
|
||||
int ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
sshc.my->wait_on_socket();
|
||||
ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA );
|
||||
}
|
||||
ec = libssh2_channel_flush_ex( chan, 0 );
|
||||
ec = libssh2_channel_flush( chan );
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
sshc.my->wait_on_socket();
|
||||
ec = libssh2_channel_flush_ex( chan, 0 );
|
||||
ec = libssh2_channel_flush( chan );
|
||||
}
|
||||
if( ec < 0 ) {
|
||||
FC_THROW_REPORT( "ssh flush failed", fc::value().set( "channel_error", ec) );
|
||||
}
|
||||
*/
|
||||
}
|
||||
int detail::process_impl::read_some( char* data, size_t len, int stream_id ){
|
||||
if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); }
|
||||
|
|
@ -958,11 +979,11 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
|
||||
ostream& detail::process_ostream::write( const char* buf, size_t len ) {
|
||||
size_t wrote = 0;
|
||||
do {
|
||||
wrote += proc.write_some( buf+wrote, len-wrote, 0 );
|
||||
} while( wrote < len );
|
||||
return *this;
|
||||
size_t wrote = 0;
|
||||
do {
|
||||
wrote += proc.write_some( buf+wrote, len-wrote, 0 );
|
||||
} while( wrote < len );
|
||||
return *this;
|
||||
}
|
||||
void detail::process_ostream::close(){
|
||||
proc.send_eof();
|
||||
|
|
@ -988,7 +1009,6 @@ namespace fc { namespace ssh {
|
|||
ec = libssh2_channel_shell(chan);
|
||||
}
|
||||
} else {
|
||||
//slog( "%s", cmd.c_str() );
|
||||
ec = libssh2_channel_exec( chan, cmd.c_str() );
|
||||
while( ec == LIBSSH2_ERROR_EAGAIN ) {
|
||||
sshc.my->wait_on_socket();
|
||||
|
|
|
|||
|
|
@ -6,23 +6,38 @@
|
|||
|
||||
int main( int argc, char** argv ) {
|
||||
try {
|
||||
// if( argc < 3 ) {
|
||||
// fc::cout<<argv[0]<<" local_path remote_path\n";
|
||||
// return -1;
|
||||
// }
|
||||
fc::cout<<"password: ";
|
||||
// fc::string pw;
|
||||
// std::cin>>pw;
|
||||
slog( "create ssh client" );
|
||||
fc::ssh::client c;
|
||||
c.connect( "dlarimer", "", "localhost" );
|
||||
fc::ssh::process proc = c.exec( "/bin/ls" );
|
||||
c.connect( "dlarimer", "rapture", "10.10.10.112" );
|
||||
slog( "connected" );
|
||||
fc::ssh::process proc = c.exec( "/bin/cat -u" );
|
||||
slog( "proc!");
|
||||
fc::string hello( "hello.............." );
|
||||
hello += hello;
|
||||
hello += hello;
|
||||
hello += hello;
|
||||
hello += hello;
|
||||
hello += hello;
|
||||
hello += "\n";
|
||||
/*
|
||||
hello += hello2;
|
||||
*/
|
||||
fc::string line;
|
||||
proc.in_stream().write(hello.c_str(), hello.size() );
|
||||
fc::getline( proc.out_stream(), line );
|
||||
fc::cout<<line<<"\n";
|
||||
while( !proc.out_stream().eof() ) {
|
||||
fc::string line;
|
||||
fc::getline( proc.out_stream(), line );
|
||||
fc::cout<<line<<"\n";
|
||||
proc.in_stream().write(hello.c_str(), hello.size() );
|
||||
proc.in_stream().flush();
|
||||
fc::getline( proc.out_stream(), line );
|
||||
}
|
||||
fc::cout<<"result: "<<proc.result()<<"\n";
|
||||
// c.scp_send( argv[1], argv[2] );
|
||||
/*
|
||||
while( true ) {
|
||||
c.scp_send( argv[1], argv[2] );
|
||||
}
|
||||
*/
|
||||
} catch ( ... ) {
|
||||
wlog( "%s", fc::except_str().c_str() );
|
||||
}
|
||||
|
|
|
|||
2
vendor/CMakeLists.txt
vendored
2
vendor/CMakeLists.txt
vendored
|
|
@ -1,3 +1,3 @@
|
|||
add_subdirectory( libssh2-1.4.2 )
|
||||
#add_subdirectory( zlib-1.2.7)
|
||||
add_subdirectory( sigar )
|
||||
#add_subdirectory( sigar )
|
||||
|
|
|
|||
2
vendor/libssh2-1.4.2/CMakeLists.txt
vendored
2
vendor/libssh2-1.4.2/CMakeLists.txt
vendored
|
|
@ -24,5 +24,5 @@ SET( sources
|
|||
src/userauth.c
|
||||
src/version.c
|
||||
)
|
||||
|
||||
add_definitions( -DLIBSSH2DEBUG )
|
||||
SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC )
|
||||
|
|
|
|||
2
vendor/libssh2-1.4.2/src/misc.h
vendored
2
vendor/libssh2-1.4.2/src/misc.h
vendored
|
|
@ -78,7 +78,7 @@ void _libssh2_htonu32(unsigned char *buf, uint32_t val);
|
|||
void _libssh2_store_u32(unsigned char **buf, uint32_t value);
|
||||
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len);
|
||||
|
||||
#if defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
#if defined(WIN32) || defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
/* provide a private one */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp);
|
||||
|
|
|
|||
Loading…
Reference in a new issue