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_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})

View file

@ -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> {

View file

@ -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...

View file

@ -1,5 +1,4 @@
#pragma once
//#include <fc/function.hpp>
#include <fc/future.hpp>
#include <functional>
#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 );
#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); } }; \

View file

@ -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);
/**

View file

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

View file

@ -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

View file

@ -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_

View file

@ -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;

View file

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

View file

@ -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();

View file

@ -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" );
}

View file

@ -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 ( ... ) {

View file

@ -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 );

View file

@ -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",

View file

@ -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();

View file

@ -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() );
}

View file

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

View file

@ -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 )

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_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);