diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index 2db45d2..5b02e24 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -171,7 +171,7 @@ namespace fc FC_DECLARE_EXCEPTION( out_of_range_exception, "Out of Range" ); /** @brief if an operation is unsupported or not valid this may be thrown */ - FC_DECLARE_EXCEPTION( invalidOperation_exception, "Invalid Operation" ); + FC_DECLARE_EXCEPTION( invalid_operation_exception, "Invalid Operation" ); /** * @brief used to report a canceled Operation diff --git a/include/fc/interprocess/iprocess.hpp b/include/fc/interprocess/iprocess.hpp index 3dcbfed..0f8671e 100644 --- a/include/fc/interprocess/iprocess.hpp +++ b/include/fc/interprocess/iprocess.hpp @@ -31,13 +31,13 @@ namespace fc * * @return *this */ - virtual iprocess& exec( const fc::path& exe, std::vector args, - const fc::path& work_dir = fc::path(), exec_opts opts = open_all ) = 0; + virtual iprocess& exec( const path& exe, std::vector args, + const path& work_dir = path(), exec_opts opts = open_all ) = 0; /** * @return blocks until the process exits */ - virtual int result() = 0; + virtual int result(const microseconds& timeout = microseconds::maximum()) = 0; /** @@ -48,16 +48,16 @@ namespace fc /** * @brief returns a stream that writes to the process' stdin */ - virtual fc::buffered_ostream_ptr in_stream() = 0; + virtual buffered_ostream_ptr in_stream() = 0; /** * @brief returns a stream that reads from the process' stdout */ - virtual fc::buffered_istream_ptr out_stream() = 0; + virtual buffered_istream_ptr out_stream() = 0; /** * @brief returns a stream that reads from the process' stderr */ - virtual fc::buffered_istream_ptr err_stream() = 0; + virtual buffered_istream_ptr err_stream() = 0; }; diff --git a/include/fc/interprocess/process.hpp b/include/fc/interprocess/process.hpp index eb13a4a..28333ef 100644 --- a/include/fc/interprocess/process.hpp +++ b/include/fc/interprocess/process.hpp @@ -20,7 +20,8 @@ namespace fc { const fc::path& work_dir = fc::path(), exec_opts opts = open_all ); - virtual int result(); + + virtual int result(const microseconds& timeout = microseconds::maximum()); virtual void kill(); virtual fc::buffered_ostream_ptr in_stream(); virtual fc::buffered_istream_ptr out_stream(); diff --git a/include/fc/io/enum_type.hpp b/include/fc/io/enum_type.hpp index 2127ac2..0406976 100644 --- a/include/fc/io/enum_type.hpp +++ b/include/fc/io/enum_type.hpp @@ -50,7 +50,7 @@ namespace fc template void to_variant( const enum_type& var, variant& vo ) { - vo = var.value; + vo = (EnumType)var.value; } template void from_variant( const variant& var, enum_type& vo ) diff --git a/include/fc/io/json.hpp b/include/fc/io/json.hpp index eada29a..4931f9b 100644 --- a/include/fc/io/json.hpp +++ b/include/fc/io/json.hpp @@ -26,6 +26,8 @@ namespace fc static string to_string( const variant& v ); static string to_pretty_string( const variant& v ); + static bool is_valid( const std::string& json_str ); + template static void save_to_file( const T& v, const fc::path& fi, bool pretty = true ) { diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp index c292bcc..ad4ac21 100644 --- a/include/fc/io/varint.hpp +++ b/include/fc/io/varint.hpp @@ -33,10 +33,12 @@ struct unsigned_int { * Uses the google protobuf algorithm for seralizing signed numbers */ struct signed_int { - signed_int( int32_t v = 0 ):value(v){} + signed_int( int64_t v = 0 ):value(v){} operator int32_t()const { return value; } template signed_int& operator=( const T& v ) { value = v; return *this; } + signed_int& operator++(int){ ++value; return *this; } + signed_int& operator++(){ ++value; return *this; } int32_t value; }; @@ -50,4 +52,16 @@ void from_variant( const variant& var, unsigned_int& vo ); } // namespace fc - +#include +namespace std +{ + template<> + struct hash + { + public: + size_t operator()(const fc::signed_int &a) const + { + return std::hash()(a.value); + } + }; +} diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index da62732..361a646 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -136,7 +136,7 @@ template<> struct reflector { \ switch( elem ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, ENUM, FIELDS ) \ default: \ - fc::throw_bad_enum_cast( BOOST_PP_STRINGIZE(elem), BOOST_PP_STRINGIZE(ENUM) ); \ + fc::throw_bad_enum_cast( fc::to_string(int64_t(elem)).c_str(), BOOST_PP_STRINGIZE(ENUM) ); \ }\ return nullptr; \ } \ diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 20cd1f6..9329023 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -21,4 +21,9 @@ namespace fc { template<> struct get_typename { static const char* name() { return "value"; } }; template<> struct get_typename> { static const char* name() { return "std::vector"; } }; + struct signed_int; + struct unsigned_int; + template<> struct get_typename { static const char* name() { return "signed_int"; } }; + template<> struct get_typename { static const char* name() { return "unsigned_int"; } }; + } diff --git a/src/exception.cpp b/src/exception.cpp index 8a73ab3..e6f7c0f 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -24,6 +24,7 @@ namespace fc eof_exception_code = 11, db_in_use_exception_code = 12, std_exception_code = 14, + invalid_operation_exception_code = 15 }; void to_variant( detail::exception_code e, variant& v ) @@ -69,6 +70,9 @@ namespace fc case db_in_use_exception_code: v = "db_in_use"; break; + case invalid_operation_exception_code: + v = "invalid_operation"; + break; case unspecified_exception_code: default: v = "unspecified"; @@ -79,20 +83,21 @@ namespace fc void from_variant( const variant& e, detail::exception_code& ll ) { string v = e.as_string(); - if( v == "unspecified" ) ll = unspecified_exception_code; - else if( v == "unhandled" ) ll = unhandled_exception_code; - else if( v == "timeout" ) ll = timeout_exception_code; - else if( v == "key_not_found" ) ll = key_not_found_exception_code; - else if( v == "bad_cast" ) ll = bad_cast_exception_code; - else if( v == "file_not_found" ) ll = file_not_found_exception_code; - else if( v == "parse_error" ) ll = parse_error_exception_code; - else if( v == "invalid_arg" ) ll = invalid_arg_exception_code; - else if( v == "out_of_range" ) ll = out_of_range_exception_code; - else if( v == "canceled" ) ll = canceled_exception_code; - else if( v == "assert" ) ll = assert_exception_code; - else if( v == "std" ) ll = std_exception_code; - else if( v == "eof" ) ll = eof_exception_code; - else if( v == "db_in_use") ll = db_in_use_exception_code; + if( v == "unspecified" ) ll = unspecified_exception_code; + else if( v == "unhandled" ) ll = unhandled_exception_code; + else if( v == "timeout" ) ll = timeout_exception_code; + else if( v == "key_not_found" ) ll = key_not_found_exception_code; + else if( v == "bad_cast" ) ll = bad_cast_exception_code; + else if( v == "file_not_found" ) ll = file_not_found_exception_code; + else if( v == "parse_error" ) ll = parse_error_exception_code; + else if( v == "invalid_arg" ) ll = invalid_arg_exception_code; + else if( v == "out_of_range" ) ll = out_of_range_exception_code; + else if( v == "canceled" ) ll = canceled_exception_code; + else if( v == "assert" ) ll = assert_exception_code; + else if( v == "std" ) ll = std_exception_code; + else if( v == "eof" ) ll = eof_exception_code; + else if( v == "db_in_use") ll = db_in_use_exception_code; + else if( v == "invalid_operation") ll = invalid_operation_exception_code; else FC_THROW_EXCEPTION( bad_cast_exception, "Invalid Error Report _code '${code}'", ("code", v) ); @@ -178,6 +183,7 @@ namespace fc FC_EXCEPTION_IMPL(key_not_found_exception) FC_EXCEPTION_IMPL(bad_cast_exception) FC_EXCEPTION_IMPL(out_of_range_exception) + FC_EXCEPTION_IMPL(invalid_operation_exception); FC_EXCEPTION_IMPL(canceled_exception) FC_EXCEPTION_IMPL(assert_exception) FC_EXCEPTION_IMPL(eof_exception) @@ -295,6 +301,8 @@ namespace fc throw eof_exception( my->_elog ); case detail::db_in_use_exception_code: throw db_in_use_exception( my->_elog ); + case detail::invalid_operation_exception_code: + throw invalid_operation_exception( my->_elog ); case detail::std_exception_code: throw std_exception( *this ); case detail::unspecified_exception_code: @@ -330,6 +338,8 @@ namespace fc return std::make_shared( my->_elog ); case detail::db_in_use_exception_code: return std::make_shared( my->_elog ); + case detail::invalid_operation_exception_code: + return std::make_shared( my->_elog ); case detail::std_exception_code: return std::make_shared( *this ); case detail::unspecified_exception_code: diff --git a/src/interprocess/process.cpp b/src/interprocess/process.cpp index 5cb46d6..5504138 100644 --- a/src/interprocess/process.cpp +++ b/src/interprocess/process.cpp @@ -179,9 +179,9 @@ fc::buffered_istream_ptr process::err_stream() { return my->_err; } -int process::result() +int process::result(const microseconds& timeout /* = microseconds::maximum() */) { - return my->_exited.wait(); + return my->_exited.wait(timeout); } } diff --git a/src/io/json.cpp b/src/io/json.cpp index a746ddf..7fa05e8 100644 --- a/src/io/json.cpp +++ b/src/io/json.cpp @@ -608,8 +608,17 @@ namespace fc void json::save_to_file( const variant& v, const fc::path& fi, bool pretty ) { + if( pretty ) + { + auto str = json::to_pretty_string( v ); + fc::ofstream o(fi); + o.write( str.c_str(), str.size() ); + } + else + { fc::ofstream o(fi); fc::to_stream( o, v ); + } } variant json::from_file( const fc::path& p ) { @@ -640,4 +649,14 @@ namespace fc return out; } + bool json::is_valid( const std::string& utf8_str ) + { + if( utf8_str.size() == 0 ) return false; + fc::stringstream in( utf8_str ); + variant_from_stream( in ); + try { in.peek(); } catch ( const eof_exception& e ) { return true; } + return false; + } + + } // fc diff --git a/src/log/logger_config.cpp b/src/log/logger_config.cpp index a8fa079..22465de 100644 --- a/src/log/logger_config.cpp +++ b/src/log/logger_config.cpp @@ -47,8 +47,8 @@ namespace fc { auto ap = appender::get( *a ); if( ap ) { lgr.add_appender(ap); } } - return reg_console_appender || reg_file_appender; } + return reg_console_appender || reg_file_appender; } catch ( exception& e ) { fc::cerr<get_socket().write( s.c_str(), s.size() ); } @@ -76,7 +76,7 @@ namespace fc { namespace http { http::server::response rep( fc::shared_ptr( new response::impl(c) ) ); auto req = c->read_request(); if( do_on_req ) do_on_req( req, rep ); - c->get_socket().close(); + c->get_socket().close(); } catch ( fc::exception& e ) { wlog( "unable to read request ${1}", ("1", e.to_detail_string() ) );//fc::except_str().c_str()); } diff --git a/src/network/tcp_socket.cpp b/src/network/tcp_socket.cpp index 67dc770..1363347 100644 --- a/src/network/tcp_socket.cpp +++ b/src/network/tcp_socket.cpp @@ -158,6 +158,14 @@ namespace fc { FC_ASSERT(my->_sock.is_open()); boost::asio::socket_base::reuse_address option(enable); my->_sock.set_option(option); +#if defined(__APPLE__) || (defined(__linux__) && defined(SO_REUSEPORT)) + // OSX needs SO_REUSEPORT in addition to SO_REUSEADDR. + // This probably needs to be set for any BSD + int reuseport_value = 1; + if (setsockopt(my->_sock.native(), SOL_SOCKET, SO_REUSEPORT, + (char*)&reuseport_value, sizeof(reuseport_value)) < 0) + wlog("Error setting SO_REUSEPORT"); +#endif // __APPLE__ } @@ -209,6 +217,14 @@ namespace fc { my = new impl; boost::asio::ip::tcp::acceptor::reuse_address option(enable); my->_accept.set_option(option); +#if defined(__APPLE__) || (defined(__linux__) && defined(SO_REUSEPORT)) + // OSX needs SO_REUSEPORT in addition to SO_REUSEADDR. + // This probably needs to be set for any BSD + int reuseport_value = 1; + if (setsockopt(my->_accept.native(), SOL_SOCKET, SO_REUSEPORT, + (char*)&reuseport_value, sizeof(reuseport_value)) < 0) + wlog("Error setting SO_REUSEPORT"); +#endif // __APPLE__ } void tcp_server::listen( uint16_t port ) {