merge latest changes

This commit is contained in:
Daniel Larimer 2013-03-01 18:56:06 -05:00
commit 7b9a14918c
21 changed files with 204 additions and 117 deletions

View file

@ -109,7 +109,7 @@ add_subdirectory(vendor)
setup_library( fc SOURCES ${sources} ) 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( 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}) 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})

View file

@ -41,6 +41,10 @@ namespace fc {
struct lexical_cast<fc::string, R> { struct lexical_cast<fc::string, R> {
static fc::string cast( const R& v ) { return to_string( v ); } 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> template<typename R>
struct lexical_cast<uint64_t, R> { struct lexical_cast<uint64_t, R> {

View file

@ -31,6 +31,11 @@ namespace fc {
ovalue meta; ovalue meta;
// key based args // 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, value&& v );
log_message& operator()( const string& arg, const value& v ); log_message& operator()( const string& arg, const value& v );
// position based args... // position based args...

View file

@ -1,5 +1,4 @@
#pragma once #pragma once
//#include <fc/function.hpp>
#include <fc/future.hpp> #include <fc/future.hpp>
#include <functional> #include <functional>
#include <boost/config.hpp> #include <boost/config.hpp>

View file

@ -75,9 +75,11 @@ void throw_bad_enum_cast( const char* k, const char* e );
fc::reflector<base>::visit( visitor ); fc::reflector<base>::visit( visitor );
#ifndef WIN32 #ifndef _MSC_VER
#define TEMPLATE template #define TEMPLATE template
#else #else
// Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name
#pragma warning( disable: 4482 )
#define TEMPLATE #define TEMPLATE
#endif #endif
@ -178,6 +180,11 @@ template<> struct reflector<TYPE> {\
#define FC_REFLECT( TYPE, MEMBERS ) \ #define FC_REFLECT( TYPE, MEMBERS ) \
FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, 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 ) \ #define FC_REFLECT_FWD( TYPE ) \
namespace fc { \ namespace fc { \
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \

View file

@ -5,6 +5,7 @@
namespace fc { namespace fc {
class path; class path;
class logger;
namespace ssh { namespace ssh {
namespace detail { namespace detail {
class client_impl; class client_impl;
@ -56,9 +57,37 @@ namespace fc {
* Because the client creates other resources that depend upon * Because the client creates other resources that depend upon
* it, it can only be created as a std::shared_ptr<client> (aka client::ptr) * it, it can only be created as a std::shared_ptr<client> (aka client::ptr)
* via client::create(); * via client::create();
*
*/ */
class client { class client {
public: 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); void connect( const fc::string& user, const fc::string& host, uint16_t port = 22);
/** /**

View file

@ -22,6 +22,8 @@ namespace std {
typedef basic_string<char, char_traits<char>, allocator<char> > string; typedef basic_string<char, char_traits<char>, allocator<char> > string;
} }
#include <string>
namespace fc { namespace fc {
// typedef std::string string; // typedef std::string string;
/** /**

View file

@ -118,7 +118,7 @@ namespace fc {
typedef fc::tuple<BOOST_PP_ENUM( n, DEDUCE_MEMBERS,unused)> type; \ 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 #undef FORWARD_PARAMS

View file

@ -1,9 +1,8 @@
#ifndef _FC_UTILITY_HPP_ #pragma once
#define _FC_UTILITY_HPP_
#include <stdint.h> #include <stdint.h>
#include <new> #include <new>
#define nullptr 0 //#define nullptr 0
typedef decltype(sizeof(int)) size_t; typedef decltype(sizeof(int)) size_t;
namespace std { namespace std {
@ -49,4 +48,3 @@ namespace fc {
a = fc::move(b); a = fc::move(b);
b = fc::move(tmp); b = fc::move(tmp);
} }
#endif // _FC_UTILITY_HPP_

View file

@ -7,6 +7,11 @@
#include <fc/optional.hpp> #include <fc/optional.hpp>
#include <boost/preprocessor/repetition/enum_params.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 { namespace fc {
template<BOOST_PP_ENUM_PARAMS(9, typename A)> struct tuple; template<BOOST_PP_ENUM_PARAMS(9, typename A)> struct tuple;

View file

@ -277,6 +277,9 @@ namespace fc {
} }
template<typename A, typename B, typename C, typename D> template<typename A, typename B, typename C, typename D>
inline void unpack( const fc::value& val, tuple<A,B,C,D>& t ) { 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) ); t.visit( tuple_from_value_visitor(val) );
} }

View file

@ -76,7 +76,7 @@ namespace fc {
} }
fc::string path::string()const { fc::string path::string()const {
return _p->string().c_str(); return _p->string();
} }
fc::path path::filename()const { fc::path path::filename()const {
return _p->filename(); return _p->filename();

View file

@ -120,9 +120,9 @@ namespace fc { namespace json {
} }
cur = cur->next; 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" );
} }

View file

@ -38,9 +38,7 @@ namespace fc { namespace json {
fc::string line; fc::string line;
fc::getline( in, line ); fc::getline( in, line );
while( !in.eof() ) { while( !in.eof() ) {
// std::cerr<<"\n**line size: "<<line.size()<<"\n\n"; fc::async( [=]() {
// slog( "line size: '%d'", line.size() );
// slog( "%s", line.c_str() );
try { try {
fc_dlog( log, "Received: '${line}'", ("line",line) ); fc_dlog( log, "Received: '${line}'", ("line",line) );
fc::value v= fc::json::from_string( line ); fc::value v= fc::json::from_string( line );
@ -51,6 +49,7 @@ namespace fc { namespace json {
fc_wlog( log, "Error handling request '${exception}'",("exception",fc::except_str()) ); fc_wlog( log, "Error handling request '${exception}'",("exception",fc::except_str()) );
return; return;
} }
});
fc::getline( in, line ); fc::getline( in, line );
} }
} catch ( ... ) { } catch ( ... ) {

View file

@ -75,7 +75,8 @@ namespace fc {
} }
void logger::log( log_message m ) { 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 ) for( auto itr = my->_appenders.begin(); itr != my->_appenders.end(); ++itr )
(*itr)->log( m ); (*itr)->log( m );

View file

@ -23,7 +23,7 @@ namespace fc {
get_logger_map().clear(); get_logger_map().clear();
get_appender_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 ) { for( size_t i = 0; i < cfg.appenders.size(); ++i ) {
appender::create( cfg.appenders[i].name, cfg.appenders[i].type, cfg.appenders[i].args ); appender::create( cfg.appenders[i].name, cfg.appenders[i].type, cfg.appenders[i].args );
// TODO... process enabled // TODO... process enabled
@ -48,7 +48,7 @@ namespace fc {
} }
logging_config logging_config::default_config() { logging_config logging_config::default_config() {
slog( "default cfg" ); //slog( "default cfg" );
logging_config cfg; logging_config cfg;
cfg.appenders.push_back( cfg.appenders.push_back(
appender_config( "stderr", "console", appender_config( "stderr", "console",

View file

@ -12,7 +12,10 @@
#include <fc/unique_lock.hpp> #include <fc/unique_lock.hpp>
#include <fc/mutex.hpp> #include <fc/mutex.hpp>
#include <fc/ip.hpp> #include <fc/ip.hpp>
#include <fc/spin_lock.hpp>
#include <fc/scoped_lock.hpp>
#include <fc/error_report.hpp> #include <fc/error_report.hpp>
#include <fc/logger.hpp>
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
#include <memory> #include <memory>
@ -79,6 +82,9 @@ namespace fc { namespace ssh {
sftp = nullptr; sftp = nullptr;
session = nullptr; session = nullptr;
knownhosts = 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_SESSION* session;
LIBSSH2_KNOWNHOSTS* knownhosts; LIBSSH2_KNOWNHOSTS* knownhosts;
@ -98,6 +104,7 @@ namespace fc { namespace ssh {
bool session_connected; bool session_connected;
fc::promise<boost::system::error_code>::ptr read_prom; fc::promise<boost::system::error_code>::ptr read_prom;
fc::promise<boost::system::error_code>::ptr write_prom; fc::promise<boost::system::error_code>::ptr write_prom;
fc::spin_lock _spin_lock;
LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type ); LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type );
static void kbd_callback(const char *name, int name_len, static void kbd_callback(const char *name, int name_len,
@ -168,16 +175,17 @@ namespace fc { namespace ssh {
bool resolved = false; bool resolved = false;
for( uint32_t i = 0; i < eps.size(); ++i ) { for( uint32_t i = 0; i < eps.size(); ++i ) {
std::stringstream ss; ss << eps[i];
try { try {
boost::system::error_code ec; boost::system::error_code ec;
std::stringstream ss; ss << eps[i]; fc_ilog( logr, "Attempting to connect to ${endpoint}", ("endpoint",ss.str().c_str()) );
slog( "Attempting to connect to %s", ss.str().c_str() );
fc::asio::tcp::connect( *sock, eps[i] ); fc::asio::tcp::connect( *sock, eps[i] );
endpt = eps[i]; endpt = eps[i];
resolved = true; resolved = true;
break; break;
} catch ( ... ) { } catch ( fc::error_report& er ) {
wlog( "%s", fc::except_str().c_str() ); fc_ilog( logr, "Failed to connect to ${endpoint}\n${error_reprot}",
("endpoint",ss.str().c_str())("error_report", er.to_detail_string()) );
sock->close(); sock->close();
} }
} }
@ -186,6 +194,9 @@ namespace fc { namespace ssh {
fc::value().set("host", hostname).set("port",port) ); fc::value().set("host", hostname).set("port",port) );
} }
session = libssh2_session_init(); 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_abstract(session) = this;
libssh2_session_set_blocking( session, 0 ); libssh2_session_set_blocking( session, 0 );
@ -216,6 +227,13 @@ namespace fc { namespace ssh {
} }
} }
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() { void close() {
if( session ) { if( session ) {
if( sftp ) { if( sftp ) {
@ -226,7 +244,7 @@ namespace fc { namespace ssh {
ec = libssh2_sftp_shutdown(sftp); ec = libssh2_sftp_shutdown(sftp);
} }
}catch(...){ }catch(...){
elog( "... caught error closing sftp session???" ); fc_wlog( logr, "caught closing sftp session" );
} }
sftp = 0; sftp = 0;
} }
@ -243,33 +261,31 @@ namespace fc { namespace ssh {
} }
session = 0; session = 0;
} catch ( ... ){ } catch ( ... ){
elog( "... caught error freeing session???" ); fc_wlog( logr, "caught freeing session" );
session = 0; session = 0;
} }
try { try {
if( sock ) { if( sock ) {
slog( "closing socket" );
sock->close(); sock->close();
} }
} catch ( ... ){ } catch ( ... ){
elog( "... caught error closing socket???" ); fc_wlog( logr, "caught error closing socket" );
} }
sock.reset(0); sock.reset(0);
try { try {
if( read_prom ) read_prom->wait(); if( read_prom ) read_prom->wait();
} catch ( ... ){ } catch ( ... ){
wlog( "caught error waiting on read prom" ); fc_wlog( logr, "caught error waiting on read" );
} }
try { try {
if( write_prom ) write_prom->wait(); if( write_prom ) write_prom->wait();
} catch ( ... ){ } catch ( ... ){
wlog( "caught error waiting on write prom" ); fc_wlog( logr, "caught error waiting on write" );
} }
} }
} }
void authenticate() { void authenticate() {
//slog( "auth" );
try { try {
char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size()); char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size());
char * msg = 0; char * msg = 0;
@ -308,7 +324,7 @@ namespace fc { namespace ssh {
keybd = true; keybd = true;
} }
else { 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() } // authenticate()
bool try_pass() { bool try_pass() {
//slog( "try pass" );
int ec = libssh2_userauth_password(session, uname.c_str(), upass.c_str() ); int ec = libssh2_userauth_password(session, uname.c_str(), upass.c_str() );
while( ec == LIBSSH2_ERROR_EAGAIN ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
wait_on_socket(); wait_on_socket();
@ -341,7 +356,6 @@ namespace fc { namespace ssh {
return !ec; return !ec;
} }
bool try_keyboard() { bool try_keyboard() {
//slog( "try keyboard" );
int ec = libssh2_userauth_keyboard_interactive(session, uname.c_str(), int ec = libssh2_userauth_keyboard_interactive(session, uname.c_str(),
&client_impl::kbd_callback); &client_impl::kbd_callback);
while( ec == LIBSSH2_ERROR_EAGAIN ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
@ -353,7 +367,6 @@ namespace fc { namespace ssh {
} }
bool try_pub_key() { bool try_pub_key() {
//slog( "try pub key" );
int ec = libssh2_userauth_publickey_fromfile(session, int ec = libssh2_userauth_publickey_fromfile(session,
uname.c_str(), uname.c_str(),
pubkey.c_str(), pubkey.c_str(),
@ -375,7 +388,7 @@ namespace fc { namespace ssh {
* @todo figure out why this method results in deadlocks... * @todo figure out why this method results in deadlocks...
*/ */
void wait_on_socket() { void wait_on_socket() {
fc::usleep( fc::microseconds(10000) ); fc::usleep(fc::microseconds(5000));
return; return;
auto dir = libssh2_session_block_directions(session); auto dir = libssh2_session_block_directions(session);
@ -383,53 +396,52 @@ namespace fc { namespace ssh {
fc::promise<boost::system::error_code>::ptr rprom, wprom; fc::promise<boost::system::error_code>::ptr rprom, wprom;
if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) { if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) {
rprom = read_prom; fc::scoped_lock<fc::spin_lock> lock(this->_spin_lock);
if(!rprom.get()) { if( !read_prom ) {
// elog( " this %2% NEW READ PROM %1% ", read_prom.get(), this );
read_prom.reset( new fc::promise<boost::system::error_code>("read_prom") ); 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(), sock->async_read_some( boost::asio::null_buffers(),
[=]( const boost::system::error_code& e, size_t ) { [=]( 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->set_value(e);
this->read_prom.reset(0); this->read_prom.reset(nullptr);
} ); } );
} else {
// elog( "already waiting on read %1%", read_prom.get() );
} }
rprom = read_prom;
} }
if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) { if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) {
wprom = write_prom; fc::scoped_lock<fc::spin_lock> lock(this->_spin_lock);
if( !write_prom ) { if( !write_prom ) {
write_prom.reset( new fc::promise<boost::system::error_code>("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(), sock->async_write_some( boost::asio::null_buffers(),
[=]( const boost::system::error_code& e, size_t ) { [=]( const boost::system::error_code& e, size_t ) {
this->write_prom->set_value(e); this->write_prom->set_value(e);
this->write_prom.reset(0); this->write_prom.reset(0);
} ); } );
} else {
// elog( "already waiting on write" );
} }
wprom = write_prom;
} }
boost::system::error_code ec; boost::system::error_code ec;
if( rprom.get() && wprom.get() ) { 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" ); wlog( "wait both dir" );
typedef fc::future<boost::system::error_code> fprom; typedef fc::future<boost::system::error_code> fprom;
fprom fw(wprom); fprom fw(wprom);
fprom fr(rprom); 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 ) { switch( r ) {
case 0: case 0:
if( wprom->wait() ) {
FC_THROW_REPORT( "Socket Error ${message}",
fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) );
}
break; break;
case 1: case 1:
if( rprom->wait() ) {
FC_THROW_REPORT( "Socket Error ${message}",
fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) );
}
break; break;
} }
} else if( rprom ) { } else if( rprom ) {
@ -444,6 +456,7 @@ namespace fc { namespace ssh {
} }
} }
} }
void init_sftp() { void init_sftp() {
if( !sftp ) { if( !sftp ) {
sftp = libssh2_sftp_init(session); 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():my( new detail::client_impl() ){}
client::~client(){} 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 ) { void client::connect( const fc::string& user, const fc::string& host, uint16_t port ) {
my->hostname = host; my->hostname = host;
my->uname = user; my->uname = user;
@ -498,7 +518,7 @@ namespace fc { namespace ssh {
if( remote_dir.filename() == fc::path(".") ) if( remote_dir.filename() == fc::path(".") )
remote_dir /= local_dir.filename(); 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 ); create_directories( remote_dir );
directory_iterator ditr(local_dir); directory_iterator ditr(local_dir);
@ -514,7 +534,7 @@ namespace fc { namespace ssh {
} else if( fc::is_regular_file(*ditr) ) { } else if( fc::is_regular_file(*ditr) ) {
scp_send( *ditr, remote_dir / (*ditr).filename() ); scp_send( *ditr, remote_dir / (*ditr).filename() );
} else { } else {
wlog( "Skipping %s", fc::canonical(*ditr).generic_string().c_str() ); fc_wlog( my->logr, "Skipping '${path}", ("path",fc::canonical(*ditr)) );
} }
++ditr; ++ditr;
} }
@ -522,7 +542,7 @@ namespace fc { namespace ssh {
void client::scp_send( const fc::path& local_path, const fc::path& remote_path, void client::scp_send( const fc::path& local_path, const fc::path& remote_path,
std::function<bool(size_t,size_t)> progress ) { 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 * 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 * 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 ); ec = libssh2_channel_close( chan );
} }
} catch ( error_report& er ) { } catch ( error_report& er ) {
wlog( "%s", er.to_detail_string().c_str() );
// clean up chan // clean up chan
int ec = libssh2_channel_free(chan ); int ec = libssh2_channel_free(chan );
while( ec == LIBSSH2_ERROR_EAGAIN ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
@ -715,7 +734,7 @@ namespace fc { namespace ssh {
ec = libssh2_sftp_shutdown(my->sftp); ec = libssh2_sftp_shutdown(my->sftp);
} }
}catch(...){ }catch(...){
elog( "... caught error closing sftp session???" ); fc_wlog( my->logr, "caught closing sftp sessionn" );
} }
my->sftp = 0; my->sftp = 0;
} }
@ -732,27 +751,26 @@ namespace fc { namespace ssh {
} }
my->session = 0; my->session = 0;
} catch ( ... ){ } catch ( ... ){
elog( "... caught error freeing session???" ); fc_wlog( my->logr, "caught error freeing session" );
my->session = 0; my->session = 0;
} }
try { try {
if( my->sock ) { if( my->sock ) {
slog( "closing socket" );
my->sock->close(); my->sock->close();
} }
} catch ( ... ){ } catch ( ... ){
elog( "... caught error closing socket???" ); fc_wlog( my->logr, "caught error closing socket" );
} }
my->sock.reset(0); my->sock.reset(0);
try { try {
if( my->read_prom ) my->read_prom->wait(); if( my->read_prom ) my->read_prom->wait();
} catch ( ... ){ } catch ( ... ){
wlog( "caught error waiting on read prom" ); fc_wlog( my->logr,"caught error waiting on read prom" );
} }
try { try {
if( my->write_prom ) my->write_prom->wait(); if( my->write_prom ) my->write_prom->wait();
} catch ( ... ){ } 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() { void detail::process_impl::flush() {
if( !chan ) return; 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); int ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
while( ec == LIBSSH2_ERROR_EAGAIN ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
sshc.my->wait_on_socket(); sshc.my->wait_on_socket();
ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA ); 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 ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
sshc.my->wait_on_socket(); sshc.my->wait_on_socket();
ec = libssh2_channel_flush_ex( chan, 0 ); ec = libssh2_channel_flush( chan );
} }
if( ec < 0 ) { if( ec < 0 ) {
FC_THROW_REPORT( "ssh flush failed", fc::value().set( "channel_error", ec) ); 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 ){ int detail::process_impl::read_some( char* data, size_t len, int stream_id ){
if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); } if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); }
@ -988,7 +1009,6 @@ namespace fc { namespace ssh {
ec = libssh2_channel_shell(chan); ec = libssh2_channel_shell(chan);
} }
} else { } else {
//slog( "%s", cmd.c_str() );
ec = libssh2_channel_exec( chan, cmd.c_str() ); ec = libssh2_channel_exec( chan, cmd.c_str() );
while( ec == LIBSSH2_ERROR_EAGAIN ) { while( ec == LIBSSH2_ERROR_EAGAIN ) {
sshc.my->wait_on_socket(); sshc.my->wait_on_socket();

View file

@ -6,23 +6,38 @@
int main( int argc, char** argv ) { int main( int argc, char** argv ) {
try { try {
// if( argc < 3 ) { slog( "create ssh client" );
// fc::cout<<argv[0]<<" local_path remote_path\n";
// return -1;
// }
fc::cout<<"password: ";
// fc::string pw;
// std::cin>>pw;
fc::ssh::client c; fc::ssh::client c;
c.connect( "dlarimer", "", "localhost" ); c.connect( "dlarimer", "rapture", "10.10.10.112" );
fc::ssh::process proc = c.exec( "/bin/ls" ); slog( "connected" );
while( !proc.out_stream().eof() ) { 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; fc::string line;
proc.in_stream().write(hello.c_str(), hello.size() );
fc::getline( proc.out_stream(), line ); fc::getline( proc.out_stream(), line );
fc::cout<<line<<"\n"; fc::cout<<line<<"\n";
while( !proc.out_stream().eof() ) {
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"; fc::cout<<"result: "<<proc.result()<<"\n";
// c.scp_send( argv[1], argv[2] ); /*
while( true ) {
c.scp_send( argv[1], argv[2] );
}
*/
} catch ( ... ) { } catch ( ... ) {
wlog( "%s", fc::except_str().c_str() ); wlog( "%s", fc::except_str().c_str() );
} }

View file

@ -1,3 +1,3 @@
add_subdirectory( libssh2-1.4.2 ) add_subdirectory( libssh2-1.4.2 )
#add_subdirectory( zlib-1.2.7) #add_subdirectory( zlib-1.2.7)
add_subdirectory( sigar ) #add_subdirectory( sigar )

View file

@ -24,5 +24,5 @@ SET( sources
src/userauth.c src/userauth.c
src/version.c src/version.c
) )
add_definitions( -DLIBSSH2DEBUG )
SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC ) SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC )

View file

@ -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_u32(unsigned char **buf, uint32_t value);
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len); 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 */ /* provide a private one */
#undef HAVE_GETTIMEOFDAY #undef HAVE_GETTIMEOFDAY
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp); int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp);