31#include <boost/shared_ptr.hpp>
32#include <boost/regex.hpp>
33#include <boost/optional/optional.hpp>
34#include <boost/utility/string_ref.hpp>
55#undef MONERO_DEFAULT_LOG_CATEGORY
56#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
106 template<
typename net_client_type>
192 bool connect(std::chrono::milliseconds timeout)
override
214 piece_of_transfer.clear();
226 return invoke(
uri,
"GET", body, timeout, ppresponse_info, additional_params);
230 inline bool invoke(
const boost::string_ref
uri,
const boost::string_ref method,
const boost::string_ref body, std::chrono::milliseconds timeout,
const http_response_info** ppresponse_info = NULL,
const fields_list& additional_params =
fields_list())
override
237 MWARNING(
"Auto connect attempt to " <<
m_host_buff <<
":" <<
m_port <<
" disabled");
240 MDEBUG(
"Reconnecting...");
248 std::string req_buff{};
249 req_buff.reserve(2048);
250 req_buff.append(method.data(), method.size()).append(
" ").append(
uri.data(),
uri.size()).append(
" HTTP/1.1\r\n");
252 add_field(req_buff,
"Content-Length", std::to_string(body.size()));
255 for(
const auto& field : additional_params)
258 for (
unsigned sends = 0; sends < 2; ++sends)
260 const std::size_t initial_size = req_buff.size();
261 const auto auth =
m_auth.get_auth_field(method,
uri);
269 CHECK_AND_ASSERT_MES(
res,
false,
"HTTP_CLIENT: Failed to SEND");
272 CHECK_AND_ASSERT_MES(
res,
false,
"HTTP_CLIENT: Failed to SEND");
294 LOG_ERROR(
"Bad server response for authentication");
297 req_buff.resize(initial_size);
299 LOG_ERROR(
"Client has incorrect username/password for server requiring authentication");
306 return invoke(
uri,
"POST", body, timeout, ppresponse_info, additional_params);
309 bool test(
const std::string &
s, std::chrono::milliseconds timeout)
337 bool keep_handling =
true;
338 bool need_more_data =
true;
339 std::string recv_buffer;
346 MERROR(
"Unexpected recv fail");
349 if(!recv_buffer.size())
357 need_more_data =
false;
374 keep_handling =
false;
377 keep_handling =
false;
392 LOG_PRINT_L3(
"Returning false because of wrong state machine. state: " <<
m_state);
402 if(!recv_buff.size())
404 LOG_ERROR(
"Connection closed at handle_header");
412 if(pos != std::string::npos)
420 MDEBUG(
"Connection cancelled by on_header");
426 need_more_data =
true;
430 need_more_data =
true;
438 if(!recv_buff.size())
440 MERROR(
"Warning: Content-Len mode, but connection unexpectedly closed");
444 CHECK_AND_ASSERT_MES(
m_len_in_remain >= recv_buff.size(),
false,
"m_len_in_remain >= recv_buff.size()");
455 need_more_data =
true;
464 if(!recv_buff.size())
469 need_more_data =
true;
479 if( (ch >=
'0' && ch <=
'9')||(ch >=
'A' && ch <=
'F')||(ch >=
'a' && ch <=
'f'))
488 std::stringstream str_stream;
489 str_stream << std::hex;
490 if(!(str_stream << chunk_head && str_stream >> result_size))
501 for(std::string::iterator it = buff.begin(); it!= buff.end(); it++, offset++)
505 if(*it ==
'\r' || *it ==
' ' )
512 std::string chunk_head = buff.substr(0, offset);
522 for(it++;it != buff.end(); it++)
530 LOG_ERROR(
"http_stream_filter: Wrong last chunk terminator");
539 buff.erase(buff.begin(), ++it);
556 if(!recv_buff.size())
558 MERROR(
"Warning: CHUNKED mode, but connection unexpectedly closed");
564 bool is_matched =
false;
570 need_more_data =
true;
588 LOG_ERROR(
"http_stream_filter::handle_chunked(*) Failed to get length from chunked head:" <<
m_chunked_cache);
595 need_more_data =
true;
611 std::string chunk_body;
638 LOG_ERROR(
"http_stream_filter::handle_chunked(): Wrong state" <<
m_chunked_state);
648 MTRACE(
"http_stream_filter::parse_cached_header(*)");
650 const char *ptr = m_cache_to_process.c_str();
651 while (ptr[0] !=
'\r' || ptr[1] !=
'\n')
657 const char *key_pos = ptr;
658 while (isalnum(*ptr) || *ptr ==
'_' || *ptr ==
'-')
660 const char *key_end = ptr;
664 CHECK_AND_ASSERT_MES(*ptr ==
':',
true,
"http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
667 while (isblank(*ptr))
669 const char *value_pos = ptr;
670 while (*ptr !=
'\r' && *ptr !=
'\n')
672 const char *value_end = ptr;
674 while (value_end > value_pos && isblank(*(value_end-1)))
678 CHECK_AND_ASSERT_MES(*ptr ==
'\n',
true,
"http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process);
681 const std::string
key = std::string(key_pos, key_end - key_pos);
682 const std::string
value = std::string(value_pos, value_end - value_pos);
716 CHECK_AND_ASSERT_MES(!memcmp(ptr,
"HTTP/", 5),
false,
"Invalid first response line: " +
m_header_cache);
721 ul = strtoul(ptr, &end, 10);
722 CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end ==
'.',
false,
"Invalid first response line: " +
m_header_cache);
726 ul = strtoul(ptr, &end, 10);
727 CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end),
false,
"Invalid first response line: " +
m_header_cache +
", ptr: " << ptr);
730 while (isblank(*ptr))
733 ul = strtoul(ptr, &end, 10);
734 CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 &&
isspace(*end),
false,
"Invalid first response line: " +
m_header_cache);
738 while (*ptr !=
'\r' && *ptr !=
'\n')
742 CHECK_AND_ASSERT_MES(*ptr ==
'\n',
false,
"Invalid first response line: " <<
m_header_cache);
751 STATIC_REGEXP_EXPR_1(rexp_match_gzip,
"^.*?((gzip)|(deflate))", boost::regex::icase | boost::regex::normal);
753 if(boost::regex_search(
m_response_info.m_header_info.m_content_encoding,
result, rexp_match_gzip, boost::match_default) &&
result[0].matched)
756 LOG_ERROR(
"GZIP encoding not supported");
771 std::string fake_str;
774 CHECK_AND_ASSERT_MES(
res,
false,
"http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " <<
m_header_cache);
779 bool content_len_valid =
false;
796 LOG_ERROR(
"Wrong Transfer-Encoding:" <<
m_response_info.m_header_info.m_transfer_encoding);
807 if(!content_len_valid)
809 LOG_ERROR(
"http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<<
m_response_info.m_header_info.m_content_length);
830 LOG_ERROR(
"Unsupported MULTIPART BODY.");
835 MERROR(
"Undefined transfer type, consider http_body_transfer_connection_close method. header: " <<
m_header_cache);
843 STATIC_REGEXP_EXPR_1(rexp_match_close,
"^\\s*close", boost::regex::icase | boost::regex::normal);
845 if(boost::regex_search(
str,
result, rexp_match_close, boost::match_default) &&
result[0].matched)
854 STATIC_REGEXP_EXPR_1(rexp_match_multipart_type,
"^\\s*multipart/([\\w\\-]+); boundary=((\"(.*?)\")|(\\\\\"(.*?)\\\\\")|([^\\s;]*))", boost::regex::icase | boost::regex::normal);
856 if(boost::regex_search(head_info.
m_content_type,
result, rexp_match_multipart_type, boost::match_default) &&
result[0].matched)
860 else if(
result[6].matched)
862 else if(
result[7].matched)
866 LOG_ERROR(
"Failed to match boundary in content-type=" << head_info.
m_content_type);
#define s(x, c)
Definition aesb.c:47
Definition http_client_base.h:61
abstract_http_client()
Definition abstract_http_client.h:64
bool set_server(const std::string &address, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect)
Definition abstract_http_client.cpp:134
Implements RFC 2617 digest auth. Digests from RFC 7616 can be added.
Definition http_auth.h:95
@ kSuccess
Definition http_auth.h:97
@ kParseFailure
Definition http_auth.h:97
@ kBadPassword
Definition http_auth.h:97
Definition http_client.h:108
void set_connector(F connector)
Definition http_client.h:186
critical_section m_lock
Definition http_client.h:144
void set_auto_connect(bool auto_connect) override
Definition http_client.h:180
bool analize_cached_header_and_invoke_state()
Definition http_client.h:767
bool set_reply_content_encoder()
Definition http_client.h:749
blocked_mode_client m_net_client
Definition http_client.h:130
boost::shared_ptr< i_sub_handler > m_pcontent_encoding_handler
Definition http_client.h:139
http_simple_client_template()
Definition http_client.h:147
bool is_multipart_body(const http_header_info &head_info, OUT std::string &boundary)
Definition http_client.h:851
std::string m_chunked_cache
Definition http_client.h:142
bool m_auto_connect
Definition http_client.h:143
virtual bool handle_target_data(std::string &piece_of_transfer) override
Definition http_client.h:210
bool handle_body_connection_close(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:461
bool is_connected(bool *ssl=NULL) override
Definition http_client.h:204
bool test(const std::string &s, std::chrono::milliseconds timeout)
Definition http_client.h:309
size_t m_len_in_summary
Definition http_client.h:136
bool connect(std::chrono::milliseconds timeout) override
Definition http_client.h:192
chunked_state m_chunked_state
Definition http_client.h:141
std::string m_header_cache
Definition http_client.h:134
bool parse_header(http_header_info &body_info, const std::string &m_cache_to_process)
Definition http_client.h:646
bool handle_body_content_len(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:435
void wipe_response()
Definition http_client.h:327
bool get_len_from_chunk_head(const std::string &chunk_head, size_t &result_size)
Definition http_client.h:486
chunked_state
Definition http_client.h:122
@ http_chunked_state_done
Definition http_client.h:125
@ http_chunked_state_chunk_head
Definition http_client.h:123
@ http_chunked_state_undefined
Definition http_client.h:126
@ http_chunked_state_chunk_body
Definition http_client.h:124
bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string &body=std::string(), const http_response_info **ppresponse_info=NULL, const fields_list &additional_params=fields_list()) override
Definition http_client.h:223
bool handle_body_body_chunked(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:553
void set_server(std::string host, std::string port, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect) override
Definition http_client.h:170
bool invoke_post(const boost::string_ref uri, const std::string &body, std::chrono::milliseconds timeout, const http_response_info **ppresponse_info=NULL, const fields_list &additional_params=fields_list()) override
Definition http_client.h:303
uint64_t get_bytes_received() const override
Definition http_client.h:322
bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info **ppresponse_info=NULL, const fields_list &additional_params=fields_list()) override
Definition http_client.h:230
bool handle_reciev(std::chrono::milliseconds timeout)
Definition http_client.h:334
http_response_info m_response_info
Definition http_client.h:135
size_t m_len_in_remain
Definition http_client.h:137
bool is_hex_symbol(char ch)
Definition http_client.h:476
reciev_machine_state m_state
Definition http_client.h:140
bool disconnect() override
Definition http_client.h:198
bool get_chunk_head(std::string &buff, size_t &chunk_size, bool &is_matched)
Definition http_client.h:497
reciev_machine_state
Definition http_client.h:111
@ reciev_machine_state_body_connection_close
Definition http_client.h:114
@ reciev_machine_state_error
Definition http_client.h:117
@ reciev_machine_state_body_content_len
Definition http_client.h:113
@ reciev_machine_state_header
Definition http_client.h:112
@ reciev_machine_state_body_chunked
Definition http_client.h:115
@ reciev_machine_state_done
Definition http_client.h:116
const std::string & get_host() const
Definition http_client.h:165
virtual bool on_header(const http_response_info &headers)
Definition http_client.h:218
bool is_connection_close_field(const std::string &str)
Definition http_client.h:841
http_client_auth m_auth
Definition http_client.h:133
const std::string & get_port() const
Definition http_client.h:166
bool handle_header(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:398
std::string m_port
Definition http_client.h:132
std::string m_host_buff
Definition http_client.h:131
uint64_t get_bytes_sent() const override
Definition http_client.h:317
bool analize_first_response_line()
Definition http_client.h:712
const char * res
Definition hmac_keccak.cpp:42
const char * key
Definition hmac_keccak.cpp:40
epee::critical_section gregexp_lock
bool isdigit(char c)
Definition parserse_base_utils.h:91
bool isspace(char c)
Definition parserse_base_utils.h:86
http_simple_client_template< blocked_mode_client > http_simple_client
Definition http_client.h:877
static void add_field(std::string &out, const boost::string_ref name, const boost::string_ref value)
Definition http_base.h:73
std::list< std::pair< std::string, std::string > > fields_list
Definition http_base.h:67
@ e_ssl_support_autodetect
Definition net_ssl.h:52
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
const char *const str
Definition portlistingparse.c:23
#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags)
Definition reg_exp_definer.h:48
#define F(w, k)
Definition sha512-blocks.c:61
tools::wallet2::message_signature_result_t result
Definition signature.cpp:62
unsigned __int64 uint64_t
Definition stdint.h:136
Definition http_base.h:164
Definition http_client_base.h:54
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153