diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index c0b57596..515da64a 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -38,9 +38,9 @@ #include "net_helper.h" #include "http_client_base.h" -//#ifdef HTTP_ENABLE_GZIP +#ifdef HTTP_ENABLE_GZIP #include "gzip_encoding.h" -//#endif +#endif #include "string_tools.h" #include "reg_exp_definer.h" @@ -200,8 +200,8 @@ using namespace std; namespace http { - - class http_simple_client: public i_target_handler + template + class http_simple_client_t: public i_target_handler { public: @@ -227,14 +227,14 @@ using namespace std; }; - blocked_mode_client m_net_client; + blocked_mode_client_t m_net_client; std::string m_host_buff; std::string m_port; - //unsigned int m_timeout; - unsigned int m_connection_timeout; - unsigned int m_recv_timeout; + unsigned int m_timeout; std::string m_header_cache; http_response_info m_response_info; + size_t m_len_in_summary; + size_t m_len_in_remain; //std::string* m_ptarget_buffer; boost::shared_ptr m_pcontent_encoding_handler; reciev_machine_state m_state; @@ -242,10 +242,6 @@ using namespace std; std::string m_chunked_cache; critical_section m_lock; - protected: - uint64_t m_len_in_summary; - uint64_t m_len_in_remain; - public: void set_host_name(const std::string& name) { @@ -253,37 +249,24 @@ using namespace std; m_host_buff = name; } - boost::asio::ip::tcp::socket& get_socket() - { - return m_net_client.get_socket(); - } + //boost::asio::ip::tcp::socket& get_socket() + //{ + // return m_net_client.get_socket(); + //} bool connect(const std::string& host, int port, unsigned int timeout) { return connect(host, std::to_string(port), timeout); } - - bool set_timeouts(unsigned int connection_timeout, unsigned int recv_timeout) - { - m_connection_timeout = connection_timeout; - m_recv_timeout = recv_timeout; - return true; - } - - bool connect(const std::string& host, std::string port) + bool connect(const std::string& host, const std::string& port, unsigned int timeout) { CRITICAL_REGION_LOCAL(m_lock); m_host_buff = host; m_port = port; + m_timeout = timeout; - return m_net_client.connect(host, port, m_connection_timeout, m_recv_timeout); - } - - bool connect(const std::string& host, const std::string& port, unsigned int timeout) - { - m_connection_timeout = m_recv_timeout = timeout; - return connect(host, port); + return m_net_client.connect(host, port, timeout, timeout); } //--------------------------------------------------------------------------- bool disconnect() @@ -320,7 +303,7 @@ using namespace std; if(!is_connected()) { LOG_PRINT("Reconnecting...", LOG_LEVEL_3); - if(!connect(m_host_buff, m_port)) + if(!connect(m_host_buff, m_port, m_timeout)) { LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_3); return false; @@ -464,14 +447,7 @@ using namespace std; } CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); m_len_in_remain -= recv_buff.size(); - bool r = m_pcontent_encoding_handler->update_in(recv_buff); - //CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_pcontent_encoding_handler->update_in returned false"); - if (!r) - { - m_state = reciev_machine_state_error; - disconnect(); - return false; - } + m_pcontent_encoding_handler->update_in(recv_buff); if(m_len_in_remain == 0) m_state = reciev_machine_state_done; @@ -507,7 +483,7 @@ using namespace std; } //--------------------------------------------------------------------------- inline - bool get_len_from_chunk_head(const std::string &chunk_head, uint64_t& result_size) + bool get_len_from_chunk_head(const std::string &chunk_head, size_t& result_size) { std::stringstream str_stream; str_stream << std::hex; @@ -518,7 +494,7 @@ using namespace std; } //--------------------------------------------------------------------------- inline - bool get_chunk_head(std::string& buff, uint64_t& chunk_size, bool& is_matched) + bool get_chunk_head(std::string& buff, size_t& chunk_size, bool& is_matched) { is_matched = false; size_t offset = 0; @@ -831,7 +807,7 @@ using namespace std; return false; }else { //Apparently there are no signs of the form of transfer, will receive data until the connection is closed - m_state = reciev_machine_state_body_connection_close; + m_state = reciev_machine_state_error; LOG_PRINT("Undefinded transfer type, consider http_body_transfer_connection_close method. header: " << m_header_cache, LOG_LEVEL_2); return false; } @@ -874,13 +850,14 @@ using namespace std; return true; } }; - // class http_simple_client - + typedef http_simple_client_t http_simple_client; + typedef http_simple_client_t https_simple_client; /************************************************************************/ /* */ /************************************************************************/ + //inline template bool invoke_request(const std::string& url, t_transport& tr, unsigned int timeout, const http_response_info** ppresponse_info, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) { @@ -894,150 +871,13 @@ using namespace std; if(!u_c.port) u_c.port = 80;//default for http - if (!tr.connect(u_c.host, static_cast(u_c.port), timeout)) - { - LOG_PRINT_L2("invoke_request: cannot connect to " << u_c.host << ":" << u_c.port); - return false; - } + res = tr.connect(u_c.host, static_cast(u_c.port), timeout); + CHECK_AND_ASSERT_MES(res, false, "failed to connect " << u_c.host << ":" << u_c.port); } return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params); } - struct idle_handler_base - { - virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) = 0; - virtual ~idle_handler_base() {} - }; - - template - struct idle_handler : public idle_handler_base - { - callback_t m_cb; - - idle_handler(callback_t cb) : m_cb(cb) {} - virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - return m_cb(piece_of_data, total_bytes, received_bytes); - } - }; - - class interruptible_http_client : public http_simple_client - { - std::shared_ptr m_pcb; - bool m_permanent_error = false; - - virtual bool handle_target_data(std::string& piece_of_transfer) - { - bool r = m_pcb->do_call(piece_of_transfer, m_len_in_summary, m_len_in_summary - m_len_in_remain); - piece_of_transfer.clear(); - return r; - } - - public: - template - bool invoke_cb(callback_t cb, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) - { - m_pcb.reset(new idle_handler(cb)); - const http_response_info* p_hri = nullptr; - bool r = invoke_request(url, *this, timeout, &p_hri, method, body, additional_params); - if (p_hri && !(p_hri->m_response_code >= 200 && p_hri->m_response_code < 300)) - { - LOG_PRINT_L0("HTTP request to " << url << " failed with code: " << p_hri->m_response_code); - m_permanent_error = true; - return false; - } - return r; - } - - template - bool download(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) - { - std::ofstream fs; - fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc); - if (!fs.is_open()) - { - LOG_ERROR("Fsiled to open " << path_for_file); - return false; - } - auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - fs.write(piece_of_data.data(), piece_of_data.size()); - return cb(total_bytes, received_bytes); - }; - bool r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params); - fs.close(); - return r; - } - - // - template - bool download_and_unzip(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), uint64_t fails_count = 1000, const fields_list& additional_params = fields_list()) - { - std::ofstream fs; - fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc); - if (!fs.is_open()) - { - LOG_ERROR("Fsiled to open " << path_for_file); - return false; - } - std::string buff; - gzip_decoder_lambda zip_decoder; - uint64_t state_total_bytes = 0; - uint64_t state_received_bytes_base = 0; - uint64_t state_received_bytes_current = 0; - bool stopped = false; - auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - //remember total_bytes only for first attempt, where fetched full lenght of the file - if (!state_total_bytes) - state_total_bytes = total_bytes; - - buff += piece_of_data; - return zip_decoder.update_in(buff, [&](const std::string& unpacked_buff) - { - state_received_bytes_current = received_bytes; - fs.write(unpacked_buff.data(), unpacked_buff.size()); - stopped = !cb(unpacked_buff, state_total_bytes, state_received_bytes_base + received_bytes); - return !stopped; - }); - }; - uint64_t current_err_count = 0; - bool r = false; - m_permanent_error = false; - while (!r && current_err_count < fails_count) - { - LOG_PRINT_L0("Attempt " << current_err_count + 1 << "/" << fails_count << " to get " << url << " (offset:" << state_received_bytes_base << ")"); - fields_list additional_params_local = additional_params; - additional_params_local.push_back(std::make_pair("Range", std::string("bytes=") + std::to_string(state_received_bytes_base) + "-")); - r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params_local); - if (!r) - { - if (stopped || m_permanent_error) - break; - current_err_count++; - state_received_bytes_base += state_received_bytes_current; - state_received_bytes_current = 0; - boost::this_thread::sleep_for(boost::chrono::milliseconds(2000)); - } - } - - if (current_err_count >= fails_count) - { - LOG_PRINT_YELLOW("Downloading from " << url << " FAILED as it's reached maximum (" << fails_count << ") number of attempts. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0); - } - else if (m_permanent_error) - { - LOG_PRINT_YELLOW("Downloading from " << url << " FAILED due to permanent HTTP error. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0); - } - - fs.close(); - return r; - } - }; - - - } // namespace http - -} // namespace net_utils -} // namespace epee + } +} +} diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 72ff4e75..8f391994 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -38,12 +38,14 @@ #include #include #include +#include #include #include #include #include #include "net/net_utils_base.h" #include "misc_language.h" +#include "misc_helpers.h" //#include "profile_tools.h" #include "../string_tools.h" @@ -54,637 +56,708 @@ namespace epee { -namespace net_utils -{ + namespace net_utils + { - class blocked_mode_client - { - - - struct handler_obj - { - handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred) - {} - handler_obj(const handler_obj& other_obj):ref_error(other_obj.ref_error), ref_bytes_transferred(other_obj.ref_bytes_transferred) - {} - - boost::system::error_code& ref_error; - size_t& ref_bytes_transferred; - - void operator()(const boost::system::error_code& error, // Result of operation. - std::size_t bytes_transferred // Number of bytes read. - ) - { - ref_error = error; - ref_bytes_transferred = bytes_transferred; - } - }; - - public: - inline - blocked_mode_client():m_socket(m_io_service), - m_initialized(false), - m_connected(false), - m_deadline(m_io_service), - m_shutdowned(0), - m_connect_timeout{}, - m_reciev_timeout{} - { - - - m_initialized = true; + template + struct socket_backend; - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - - } - inline - ~blocked_mode_client() - { - NESTED_TRY_ENTRY(); - - //profile_tools::local_coast lc("~blocked_mode_client()", 3); - shutdown(); - - NESTED_CATCH_ENTRY(__func__); - } - - inline void set_recv_timeout(int reciev_timeout) - { - m_reciev_timeout = reciev_timeout; - } - - inline - bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") + template<> + struct socket_backend { - return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip); - } + socket_backend(boost::asio::io_service& _io_service): m_ssl_context(boost::asio::ssl::context::sslv23), m_socket(_io_service, m_ssl_context) + { + // Create a context that uses the default paths for + // finding CA certificates. + m_ssl_context.set_default_verify_paths(); + } - inline - bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") - { - m_connect_timeout = connect_timeout; - m_reciev_timeout = reciev_timeout; - m_connected = false; - if(!m_reciev_timeout) - m_reciev_timeout = m_connect_timeout; + boost::asio::ip::tcp::socket& get_socket() + { + return m_socket.next_layer(); + } - try - { - m_socket.close(); - // Get a list of endpoints corresponding to the server name. - + auto& get_stream() + { + return m_socket; + } - ////////////////////////////////////////////////////////////////////////// + void on_after_connect() + { + m_socket.handshake(boost::asio::ssl::stream_base::client); + } - boost::asio::ip::tcp::resolver resolver(m_io_service); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << addr); - return false; - } + private: + boost::asio::ssl::context m_ssl_context; + boost::asio::ssl::stream m_socket; + }; - ////////////////////////////////////////////////////////////////////////// + template<> + struct socket_backend + { + socket_backend(boost::asio::io_service& _io_service): m_socket(_io_service) + {} + + boost::asio::ip::tcp::socket& get_socket() + { + return m_socket; + } + + boost::asio::ip::tcp::socket& get_stream() + { + return m_socket; + } + + void on_after_connect() + { + + } + private: + boost::asio::ip::tcp::socket m_socket; + }; - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - m_socket.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); - m_socket.bind(local_endpoint); - } + template + class blocked_mode_client_t + { + struct handler_obj + { + handler_obj(boost::system::error_code& error, size_t& bytes_transferred) :ref_error(error), ref_bytes_transferred(bytes_transferred) + {} + handler_obj(const handler_obj& other_obj) :ref_error(other_obj.ref_error), ref_bytes_transferred(other_obj.ref_bytes_transferred) + {} - - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout)); + boost::system::error_code& ref_error; + size_t& ref_bytes_transferred; + + void operator()(const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes read. + ) + { + ref_error = error; + ref_bytes_transferred = bytes_transferred; + } + }; + + public: + inline + blocked_mode_client_t() :m_sct_back(m_io_service), + m_initialized(false), + m_connected(false), + m_deadline(m_io_service), + m_shutdowned(0), + m_connect_timeout{}, + m_reciev_timeout{} + { - boost::system::error_code ec = boost::asio::error::would_block; - - //m_socket.connect(remote_endpoint); - m_socket.async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (!ec && m_socket.is_open()) - { - m_connected = true; - m_deadline.expires_at(boost::posix_time::pos_infin); - return true; - }else - { - LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); - return false; - } - - } - catch(const boost::system::system_error& er) - { - LOG_PRINT("Some problems at connect, message: " << er.what(), LOG_LEVEL_4); - return false; - } - catch(...) - { - LOG_PRINT("Some fatal problems.", LOG_LEVEL_4); - return false; - } - - return true; - } + m_initialized = true; - inline - bool disconnect() - { - try - { - if(m_connected) - { - m_connected = false; - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); - - } - } - - catch(const boost::system::system_error& /*er*/) - { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); - return false; - } - catch(...) - { - //LOG_ERROR("Some fatal problems."); - return false; - } - return true; - } + // No deadline is required until the first socket operation is started. We + // set the deadline to positive infinity so that the actor takes no action + // until a specific deadline is set. + m_deadline.expires_at(boost::posix_time::pos_infin); + + // Start the persistent actor that checks for deadline expiry. + check_deadline(); + + } + inline + ~blocked_mode_client_t() + { + NESTED_TRY_ENTRY(); + + //profile_tools::local_coast lc("~blocked_mode_client()", 3); + shutdown(); + + NESTED_CATCH_ENTRY(__func__); + } + + inline void set_recv_timeout(int reciev_timeout) + { + m_reciev_timeout = reciev_timeout; + } + + inline + bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") + { + return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip); + } + + inline + bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") + { + m_connect_timeout = connect_timeout; + m_reciev_timeout = reciev_timeout; + m_connected = false; + if (!m_reciev_timeout) + m_reciev_timeout = m_connect_timeout; + + try + { + m_sct_back.get_socket().close(); + // Get a list of endpoints corresponding to the server name. - inline - bool send(const std::string& buff) - { + ////////////////////////////////////////////////////////////////////////// - try - { - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + boost::asio::ip::tcp::resolver resolver(m_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); + boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + boost::asio::ip::tcp::resolver::iterator end; + if (iterator == end) + { + LOG_ERROR("Failed to resolve " << addr); + return false; + } - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; + ////////////////////////////////////////////////////////////////////////// - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(buff), boost::lambda::var(ec) = boost::lambda::_1); - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } + //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); + boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - if (ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); + + m_sct_back.get_socket().open(remote_endpoint.protocol()); + if (bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "") + { + boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); + m_sct_back.get_socket().bind(local_endpoint); + } + + + m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout)); + + + boost::system::error_code ec = boost::asio::error::would_block; + + //m_sct_back.get_socket().connect(remote_endpoint); + m_sct_back.get_socket().async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); + while (ec == boost::asio::error::would_block) + { + m_io_service.run_one(); + } + + if (!ec && m_sct_back.get_socket().is_open()) + { + m_sct_back.on_after_connect(); + m_connected = true; + m_deadline.expires_at(boost::posix_time::pos_infin); + return true; + } + else + { + LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); + return false; + } + + } + catch (const boost::system::system_error& er) + { + LOG_PRINT("Some problems at connect, message: " << er.what(), LOG_LEVEL_4); + return false; + } + catch (...) + { + LOG_PRINT("Some fatal problems.", LOG_LEVEL_4); + return false; + } + + return true; + } + + + inline + bool disconnect() + { + try + { + if (m_connected) + { + m_connected = false; + m_sct_back.get_socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both); + + } + } + + catch (const boost::system::system_error& /*er*/) + { + //LOG_ERROR("Some problems at disconnect, message: " << er.what()); + return false; + } + catch (...) + { + //LOG_ERROR("Some fatal problems."); + return false; + } + return true; + } + + + inline + bool send(const std::string& buff) + { + + try + { + m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + + // Set up the variable that receives the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + boost::system::error_code ec = boost::asio::error::would_block; + + // Start the asynchronous operation itself. The boost::lambda function + // object is used as a callback and will update the ec variable when the + // operation completes. The blocking_udp_client.cpp example shows how you + // can use boost::bind rather than boost::lambda. + boost::asio::async_write(m_sct_back.get_stream(), boost::asio::buffer(buff), boost::lambda::var(ec) = boost::lambda::_1); + + // Block until the asynchronous operation has completed. + while (ec == boost::asio::error::would_block) + { + m_io_service.run_one(); + } + + if (ec) + { + LOG_PRINT_L3("Problems at write: " << ec.message()); + m_connected = false; + return false; + } + else + { + m_deadline.expires_at(boost::posix_time::pos_infin); + } + } + + catch (const boost::system::system_error& er) + { + LOG_ERROR("Some problems at connect, message: " << er.what()); + return false; + } + catch (...) + { + LOG_ERROR("Some fatal problems."); + return false; + } + + return true; + } + + inline + bool send(const void* data, size_t sz) + { + try + { + /* + m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + + // Set up the variable that receives the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + boost::system::error_code ec = boost::asio::error::would_block; + + // Start the asynchronous operation itself. The boost::lambda function + // object is used as a callback and will update the ec variable when the + // operation completes. The blocking_udp_client.cpp example shows how you + // can use boost::bind rather than boost::lambda. + boost::asio::async_write(m_sct_back.get_socket(), boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); + + // Block until the asynchronous operation has completed. + while (ec == boost::asio::error::would_block) + { + m_io_service.run_one(); + } + */ + boost::system::error_code ec; + + size_t writen = m_sct_back.get_stream().write_some(boost::asio::buffer(data, sz), ec); + + + + if (!writen || ec) + { + LOG_PRINT_L3("Problems at write: " << ec.message()); + m_connected = false; + return false; + } + else + { + m_deadline.expires_at(boost::posix_time::pos_infin); + } + } + + catch (const boost::system::system_error& er) + { + LOG_ERROR("Some problems at send, message: " << er.what()); m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } + return false; + } + catch (...) + { + LOG_ERROR("Some fatal problems."); + return false; + } - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } + return true; + } - return true; - } + bool is_connected() + { + return m_connected && m_sct_back.get_socket().is_open(); + //TRY_ENTRY() + //return m_socket.is_open(); + //CATCH_ENTRY_L0("is_connected", false) + } - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + inline + bool recv(std::string& buff) + { - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; + try + { + // Set a deadline for the asynchronous operation. Since this function uses + // a composed operation (async_read_until), the deadline applies to the + // entire operation, rather than individual reads from the socket. + m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); + // Set up the variable that receives the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + //boost::system::error_code ec = boost::asio::error::would_block; - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - */ - boost::system::error_code ec; + // Start the asynchronous operation itself. The boost::lambda function + // object is used as a callback and will update the ec variable when the + // operation completes. The blocking_udp_client.cpp example shows how you + // can use boost::bind rather than boost::lambda. - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); - + boost::system::error_code ec = boost::asio::error::would_block; + size_t bytes_transfered = 0; + + handler_obj hndlr(ec, bytes_transfered); + + char local_buff[10000] = { 0 }; + //m_socket.async_read_some(boost::asio::buffer(local_buff, sizeof(local_buff)), hndlr); + boost::asio::async_read(m_sct_back.get_stream(), boost::asio::buffer(local_buff, sizeof(local_buff)), boost::asio::transfer_at_least(1), hndlr); + + // Block until the asynchronous operation has completed. + while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) + { + m_io_service.run_one(); + } - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); + if (ec) + { + LOG_PRINT_L4("READ ENDS: Connection err_code " << ec.value()); + if (ec == boost::asio::error::eof) + { + LOG_PRINT_L4("Connection err_code eof."); + //connection closed there, empty + return true; + } + + LOG_PRINT_L3("Problems at read: " << ec.message()); + m_connected = false; + return false; + } + else + { + LOG_PRINT_L4("READ ENDS: Success. bytes_tr: " << bytes_transfered); + m_deadline.expires_at(boost::posix_time::pos_infin); + } + + /*if(!bytes_transfered) + return false;*/ + + buff.assign(local_buff, bytes_transfered); + return true; + } + + catch (const boost::system::system_error& er) + { + LOG_ERROR("Some problems at read, message: " << er.what()); m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at send, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - bool is_connected() - { - return m_connected && m_socket.is_open(); - //TRY_ENTRY() - //return m_socket.is_open(); - //CATCH_ENTRY_L0("is_connected", false) - } - - inline - bool recv(std::string& buff) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - handler_obj hndlr(ec, bytes_transfered); - - char local_buff[10000] = {0}; - //m_socket.async_read_some(boost::asio::buffer(local_buff, sizeof(local_buff)), hndlr); - boost::asio::async_read(m_socket, boost::asio::buffer(local_buff, sizeof(local_buff)), boost::asio::transfer_at_least(1), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - - if (ec) - { - LOG_PRINT_L4("READ ENDS: Connection err_code " << ec.value()); - if(ec == boost::asio::error::eof) - { - LOG_PRINT_L4("Connection err_code eof."); - //connection closed there, empty - return true; - } - - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - LOG_PRINT_L4("READ ENDS: Success. bytes_tr: " << bytes_transfered); - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - /*if(!bytes_transfered) - return false;*/ - - buff.assign(local_buff, bytes_transfered); - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } + return false; + } + catch (...) + { + LOG_ERROR("Some fatal problems at read."); + return false; + } - return false; + return false; - } + } - inline bool recv_n(std::string& buff, int64_t sz) - { + inline bool recv_n(std::string& buff, int64_t sz) + { - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + try + { + // Set a deadline for the asynchronous operation. Since this function uses + // a composed operation (async_read_until), the deadline applies to the + // entire operation, rather than individual reads from the socket. + m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; + // Set up the variable that receives the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + //boost::system::error_code ec = boost::asio::error::would_block; - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. + // Start the asynchronous operation itself. The boost::lambda function + // object is used as a callback and will update the ec variable when the + // operation completes. The blocking_udp_client.cpp example shows how you + // can use boost::bind rather than boost::lambda. - buff.resize(static_cast(sz)); - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; + buff.resize(static_cast(sz)); + boost::system::error_code ec = boost::asio::error::would_block; + size_t bytes_transfered = 0; - - handler_obj hndlr(ec, bytes_transfered); - //char local_buff[10000] = {0}; - boost::asio::async_read(m_socket, boost::asio::buffer((char*)buff.data(), buff.size()), boost::asio::transfer_at_least(buff.size()), hndlr); + handler_obj hndlr(ec, bytes_transfered); - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } + //char local_buff[10000] = {0}; + boost::asio::async_read(m_sct_back.get_stream(), boost::asio::buffer((char*)buff.data(), buff.size()), boost::asio::transfer_at_least(buff.size()), hndlr); - if (ec) - { - LOG_PRINT_L3("Problems at read: " << ec.message()); + // Block until the asynchronous operation has completed. + while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) + { + m_io_service.run_one(); + } + + if (ec) + { + LOG_PRINT_L3("Problems at read: " << ec.message()); + m_connected = false; + return false; + } + else + { + m_deadline.expires_at(boost::posix_time::pos_infin); + } + + if (bytes_transfered != buff.size()) + { + LOG_ERROR("Transferred missmatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); + return false; + } + + return true; + } + + catch (const boost::system::system_error& er) + { + LOG_ERROR("Some problems at read, message: " << er.what()); m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } + return false; + } + catch (...) + { + LOG_ERROR("Some fatal problems at read."); + return false; + } - if(bytes_transfered != buff.size()) - { - LOG_ERROR("Transferred missmatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); - return false; - } - return true; - } - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); + return false; + } + + bool shutdown() + { + m_deadline.cancel(); + boost::system::error_code ignored_ec; + m_sct_back.get_socket().cancel(ignored_ec); + m_sct_back.get_socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); + m_sct_back.get_socket().close(ignored_ec); + boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } + return true; + } + + void set_connected(bool connected) + { + m_connected = connected; + } + boost::asio::io_service& get_io_service() + { + return m_io_service; + } + + boost::asio::ip::tcp::socket& get_socket() + { + return m_sct_back.get_socket(); + } + + private: + + void check_deadline() + { + // Check whether the deadline has passed. We compare the deadline against + // the current time since a new asynchronous operation may have moved the + // deadline before this actor had a chance to run. + if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) + { + // The deadline has passed. The socket is closed so that any outstanding + // asynchronous operations are cancelled. This allows the blocked + // connect(), read_line() or write_line() functions to return. + LOG_PRINT_L3("Timed out socket"); + m_connected = false; + m_sct_back.get_socket().close(); + + // There is no longer an active deadline. The expiry is set to positive + // infinity so that the actor takes no action until a new deadline is set. + m_deadline.expires_at(boost::posix_time::pos_infin); + } + + // Put the actor back to sleep. + m_deadline.async_wait(boost::bind(&blocked_mode_client_t::check_deadline, this)); + } - return false; - } - - bool shutdown() - { - m_deadline.cancel(); - boost::system::error_code ignored_ec; - m_socket.cancel(ignored_ec); - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_socket.close(ignored_ec); - boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); - m_connected = false; - return true; - } - - void set_connected(bool connected) - { - m_connected = connected; - } - boost::asio::io_service& get_io_service() - { - return m_io_service; - } - - boost::asio::ip::tcp::socket& get_socket() - { - return m_socket; - } - - private: - - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_connected = false; - m_socket.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_deadline.async_wait(boost::bind(&blocked_mode_client::check_deadline, this)); - } - - - - protected: - boost::asio::io_service m_io_service; - boost::asio::ip::tcp::socket m_socket; - int m_connect_timeout; - int m_reciev_timeout; - bool m_initialized; - bool m_connected; - boost::asio::deadline_timer m_deadline; - volatile uint32_t m_shutdowned; - }; + protected: + boost::asio::io_service m_io_service; + socket_backend m_sct_back; + int m_connect_timeout; + int m_reciev_timeout; + bool m_initialized; + bool m_connected; + boost::asio::deadline_timer m_deadline; + volatile uint32_t m_shutdowned; + }; - /************************************************************************/ - /* */ - /************************************************************************/ - class async_blocked_mode_client: public blocked_mode_client - { - public: - async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service) - { + /************************************************************************/ + /* */ + /************************************************************************/ + template + class async_blocked_mode_client_t : public blocked_mode_client_t + { + public: + async_blocked_mode_client_t() :m_send_deadline(blocked_mode_client::m_io_service) + { - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); + // No deadline is required until the first socket operation is started. We + // set the deadline to positive infinity so that the actor takes no action + // until a specific deadline is set. + m_send_deadline.expires_at(boost::posix_time::pos_infin); - // Start the persistent actor that checks for deadline expiry. - check_send_deadline(); - } - ~async_blocked_mode_client() - { - m_send_deadline.cancel(); - } - - bool shutdown() - { - blocked_mode_client::shutdown(); - m_send_deadline.cancel(); - return true; - } + // Start the persistent actor that checks for deadline expiry. + check_send_deadline(); + } + ~async_blocked_mode_client_t() + { + m_send_deadline.cancel(); + } - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); + bool shutdown() + { + blocked_mode_client::shutdown(); + m_send_deadline.cancel(); + return true; + } - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; + inline + bool send(const void* data, size_t sz) + { + try + { + /* + m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); + // Set up the variable that receives the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + boost::system::error_code ec = boost::asio::error::would_block; - // Block until the asynchronous operation has completed. - while(ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - }*/ - - boost::system::error_code ec; + // Start the asynchronous operation itself. The boost::lambda function + // object is used as a callback and will update the ec variable when the + // operation completes. The blocking_udp_client.cpp example shows how you + // can use boost::bind rather than boost::lambda. + boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); + // Block until the asynchronous operation has completed. + while(ec == boost::asio::error::would_block) + { + m_io_service.run_one(); + }*/ - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - return false; - }else - { - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - } + boost::system::error_code ec; - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } + size_t writen = m_sct_back.get_socket().write_some(boost::asio::buffer(data, sz), ec); - return true; - } + if (!writen || ec) + { + LOG_PRINT_L3("Problems at write: " << ec.message()); + return false; + } + else + { + m_send_deadline.expires_at(boost::posix_time::pos_infin); + } + } + + catch (const boost::system::system_error& er) + { + LOG_ERROR("Some problems at connect, message: " << er.what()); + return false; + } + catch (...) + { + LOG_ERROR("Some fatal problems."); + return false; + } + + return true; + } - private: + private: - boost::asio::deadline_timer m_send_deadline; + boost::asio::deadline_timer m_send_deadline; - void check_send_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_socket.close(); + void check_send_deadline() + { + // Check whether the deadline has passed. We compare the deadline against + // the current time since a new asynchronous operation may have moved the + // deadline before this actor had a chance to run. + if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) + { + // The deadline has passed. The socket is closed so that any outstanding + // asynchronous operations are cancelled. This allows the blocked + // connect(), read_line() or write_line() functions to return. + LOG_PRINT_L3("Timed out socket"); + m_sct_back.get_socket().close(); - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } + // There is no longer an active deadline. The expiry is set to positive + // infinity so that the actor takes no action until a new deadline is set. + m_send_deadline.expires_at(boost::posix_time::pos_infin); + } - // Put the actor back to sleep. - m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this)); - } - }; -} + // Put the actor back to sleep. + m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this)); + } + }; + + typedef blocked_mode_client_t blocked_mode_client; + typedef async_blocked_mode_client_t async_blocked_mode_client; + } } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f727197e..2e717df9 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3154,6 +3154,11 @@ bool wallet2::delete_custom_asset_id(const crypto::hash& asset_id) } return true; +} +//---------------------------------------------------------------------------------------------------- +bool wallet2::load_whitelisted_tokens_list() +{ + } //---------------------------------------------------------------------------------------------------- void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) const diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c86f5b0e..d43650e6 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -897,7 +897,9 @@ namespace tools void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true); bool add_custom_asset_id(const crypto::hash& asset_id); - + bool delete_custom_asset_id(const crypto::hash& asset_id); + bool load_whitelisted_tokens_list(); + /* create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and we use deterministic origin, if given some particular htlc_hash, then we use this hash, and this means that