Monero
Loading...
Searching...
No Matches
http_client.h
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28
29#pragma once
30#include <ctype.h>
31#include <boost/shared_ptr.hpp>
32#include <boost/regex.hpp>
33#include <boost/optional/optional.hpp>
34#include <boost/utility/string_ref.hpp>
35//#include <mbstring.h>
36#include <algorithm>
37#include <cctype>
38#include <functional>
39
40#include "net_helper.h"
41#include "http_client_base.h"
42#include "string_tools.h"
44#include "reg_exp_definer.h"
46#include "http_base.h"
47#include "http_auth.h"
48#include "net_parse_helpers.h"
49#include "syncobj.h"
50
51//#include "shlwapi.h"
52
53//#pragma comment(lib, "shlwapi.lib")
54
55#undef MONERO_DEFAULT_LOG_CATEGORY
56#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
57
59
60
61namespace epee
62{
63namespace net_utils
64{
65
66 /*struct url
67 {
68 public:
69 void parse(const std::string& url_s)
70 {
71 const string prot_end("://");
72 string::const_iterator prot_i = search(url_s.begin(), url_s.end(),
73 prot_end.begin(), prot_end.end());
74 protocol_.reserve(distance(url_s.begin(), prot_i));
75 transform(url_s.begin(), prot_i,
76 back_inserter(protocol_),
77 ptr_fun<int,int>(tolower)); // protocol is icase
78 if( prot_i == url_s.end() )
79 return;
80 advance(prot_i, prot_end.length());
81 string::const_iterator path_i = find(prot_i, url_s.end(), '/');
82 host_.reserve(distance(prot_i, path_i));
83 transform(prot_i, path_i,
84 back_inserter(host_),
85 ptr_fun<int,int>(tolower)); // host is icase
86 string::const_iterator query_i = find(path_i, url_s.end(), '?');
87 path_.assign(path_i, query_i);
88 if( query_i != url_s.end() )
89 ++query_i;
90 query_.assign(query_i, url_s.end());
91 }
92
93 std::string protocol_;
94 std::string host_;
95 std::string path_;
96 std::string query_;
97 };*/
98
99
100
101
102 //---------------------------------------------------------------------------
103 namespace http
104 {
105
106 template<typename net_client_type>
108 {
109 private:
119
120
121
128
129
130 net_client_type m_net_client;
131 std::string m_host_buff;
132 std::string m_port;
134 std::string m_header_cache;
138 //std::string* m_ptarget_buffer;
139 boost::shared_ptr<i_sub_handler> m_pcontent_encoding_handler;
142 std::string m_chunked_cache;
145
146 public:
149 , m_net_client()
150 , m_host_buff()
151 , m_port()
152 , m_auth()
156 , m_len_in_remain(0)
158 , m_state()
162 , m_lock()
163 {}
164
165 const std::string &get_host() const { return m_host_buff; };
166 const std::string &get_port() const { return m_port; };
167
169
170 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
171 {
173 disconnect();
174 m_host_buff = std::move(host);
175 m_port = std::move(port);
176 m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{};
177 m_net_client.set_ssl(std::move(ssl_options));
178 }
179
180 void set_auto_connect(bool auto_connect) override
181 {
182 m_auto_connect = auto_connect;
183 }
184
185 template<typename F>
186 void set_connector(F connector)
187 {
189 m_net_client.set_connector(std::move(connector));
190 }
191
192 bool connect(std::chrono::milliseconds timeout) override
193 {
195 return m_net_client.connect(m_host_buff, m_port, timeout);
196 }
197 //---------------------------------------------------------------------------
198 bool disconnect() override
199 {
201 return m_net_client.disconnect();
202 }
203 //---------------------------------------------------------------------------
204 bool shutdown() override
205 {
206 return m_net_client.shutdown(); // no m_lock; interrupts an invoke blocked while holding it
207 }
208 //---------------------------------------------------------------------------
209 bool is_connected(bool *ssl = NULL) override
210 {
212 return m_net_client.is_connected(ssl);
213 }
214 //---------------------------------------------------------------------------
215 virtual bool handle_target_data(std::string& piece_of_transfer) override
216 {
218 m_response_info.m_body += piece_of_transfer;
219 piece_of_transfer.clear();
220 return true;
221 }
222 //---------------------------------------------------------------------------
223 virtual bool on_header(const http_response_info &headers)
224 {
225 return true;
226 }
227 //---------------------------------------------------------------------------
228 inline 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
229 {
231 return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params);
232 }
233
234 //---------------------------------------------------------------------------
235 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
236 {
238 if(!is_connected())
239 {
240 if (!m_auto_connect)
241 {
242 MWARNING("Auto connect attempt to " << m_host_buff << ":" << m_port << " disabled");
243 return false;
244 }
245 MDEBUG("Reconnecting...");
246 if(!connect(timeout))
247 {
248 MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port);
249 return false;
250 }
251 }
252
253 std::string req_buff{};
254 req_buff.reserve(2048);
255 req_buff.append(method.data(), method.size()).append(" ").append(uri.data(), uri.size()).append(" HTTP/1.1\r\n");
256 add_field(req_buff, "Host", m_host_buff);
257 add_field(req_buff, "Content-Length", std::to_string(body.size()));
258
259 //handle "additional_params"
260 for(const auto& field : additional_params)
261 add_field(req_buff, field);
262
263 for (unsigned sends = 0; sends < 2; ++sends)
264 {
265 const std::size_t initial_size = req_buff.size();
266 const auto auth = m_auth.get_auth_field(method, uri);
267 if (auth)
268 add_field(req_buff, *auth);
269
270 req_buff += "\r\n";
271 //--
272
273 bool res = m_net_client.send(req_buff, timeout);
274 CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
275 if(body.size())
276 res = m_net_client.send(body, timeout);
277 CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
278
281 if (!handle_reciev(timeout))
282 return false;
284 {
285 if(ppresponse_info)
286 *ppresponse_info = std::addressof(m_response_info);
287 return true;
288 }
289
291 {
293 break;
295 sends = 2;
296 break;
297 default:
299 LOG_ERROR("Bad server response for authentication");
300 return false;
301 }
302 req_buff.resize(initial_size); // rollback for new auth generation
303 }
304 LOG_ERROR("Client has incorrect username/password for server requiring authentication");
305 return false;
306 }
307 //---------------------------------------------------------------------------
308 inline 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
309 {
311 return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
312 }
313 //---------------------------------------------------------------------------
314 bool test(const std::string &s, std::chrono::milliseconds timeout) // TEST FUNC ONLY
315 {
317 m_net_client.set_test_data(s);
319 return handle_reciev(timeout);
320 }
321 //---------------------------------------------------------------------------
322 uint64_t get_bytes_sent() const override
323 {
324 return m_net_client.get_bytes_sent();
325 }
326 //---------------------------------------------------------------------------
328 {
329 return m_net_client.get_bytes_received();
330 }
331 //---------------------------------------------------------------------------
333 {
335 }
336 //---------------------------------------------------------------------------
337 private:
338 //---------------------------------------------------------------------------
339 inline bool handle_reciev(std::chrono::milliseconds timeout)
340 {
342 bool keep_handling = true;
343 bool need_more_data = true;
344 std::string recv_buffer;
345 while(keep_handling)
346 {
347 if(need_more_data)
348 {
349 if(!m_net_client.recv(recv_buffer, timeout))
350 {
351 MERROR("Unexpected recv fail");
353 }
354 if(!recv_buffer.size())
355 {
356 //connection is going to be closed
358 {
360 }
361 }
362 need_more_data = false;
363 }
364 switch(m_state)
365 {
367 keep_handling = handle_header(recv_buffer, need_more_data);
368 break;
370 keep_handling = handle_body_content_len(recv_buffer, need_more_data);
371 break;
373 keep_handling = handle_body_connection_close(recv_buffer, need_more_data);
374 break;
376 keep_handling = handle_body_body_chunked(recv_buffer, need_more_data);
377 break;
379 keep_handling = false;
380 break;
382 keep_handling = false;
383 break;
384 }
385
386 }
387 m_header_cache.clear();
389 {
391 disconnect();
392
393 return true;
394 }
395 else
396 {
397 LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state);
398 return false;
399 }
400 }
401 //---------------------------------------------------------------------------
402 inline
403 bool handle_header(std::string& recv_buff, bool& need_more_data)
404 {
405
407 if(!recv_buff.size())
408 {
409 LOG_ERROR("Connection closed at handle_header");
411 return false;
412 }
413
414 m_header_cache += recv_buff;
415 recv_buff.clear();
416 std::string::size_type pos = m_header_cache.find("\r\n\r\n");
417 if(pos != std::string::npos)
418 {
419 recv_buff.assign(m_header_cache.begin()+pos+4, m_header_cache.end());
420 m_header_cache.erase(m_header_cache.begin()+pos+4, m_header_cache.end());
421
423 {
425 return false;
426 }
428 {
429 MDEBUG("Connection cancelled by on_header");
431 return false;
432 }
433 m_header_cache.clear();
434 if(!recv_buff.size() && (m_state != reciev_machine_state_error && m_state != reciev_machine_state_done))
435 need_more_data = true;
436
437 return true;
438 }else
439 need_more_data = true;
440 return true;
441 }
442 //---------------------------------------------------------------------------
443 inline
444 bool handle_body_content_len(std::string& recv_buff, bool& need_more_data)
445 {
447 if(!recv_buff.size())
448 {
449 MERROR("Warning: Content-Len mode, but connection unexpectedly closed");
451 return true;
452 }
453 CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()");
454 m_len_in_remain -= recv_buff.size();
455 if (!m_pcontent_encoding_handler->update_in(recv_buff))
456 {
458 return false;
459 }
460
461 if(m_len_in_remain == 0)
463 else
464 need_more_data = true;
465
466 return true;
467 }
468 //---------------------------------------------------------------------------
469 inline
470 bool handle_body_connection_close(std::string& recv_buff, bool& need_more_data)
471 {
473 if(!recv_buff.size())
474 {
476 return true;
477 }
478 need_more_data = true;
479 m_pcontent_encoding_handler->update_in(recv_buff);
480
481
482 return true;
483 }
484 //---------------------------------------------------------------------------
485 inline bool is_hex_symbol(char ch)
486 {
487
488 if( (ch >= '0' && ch <='9')||(ch >= 'A' && ch <='F')||(ch >= 'a' && ch <='f'))
489 return true;
490 else
491 return false;
492 }
493 //---------------------------------------------------------------------------
494 inline
495 bool get_len_from_chunk_head(const std::string &chunk_head, size_t& result_size)
496 {
497 std::stringstream str_stream;
498 str_stream << std::hex;
499 if(!(str_stream << chunk_head && str_stream >> result_size))
500 return false;
501
502 return true;
503 }
504 //---------------------------------------------------------------------------
505 inline
506 bool get_chunk_head(std::string& buff, size_t& chunk_size, bool& is_matched)
507 {
508 is_matched = false;
509 size_t offset = 0;
510 for(std::string::iterator it = buff.begin(); it!= buff.end(); it++, offset++)
511 {
512 if(!is_hex_symbol(*it))
513 {
514 if(*it == '\r' || *it == ' ' )
515 {
516 offset--;
517 continue;
518 }
519 else if(*it == '\n')
520 {
521 std::string chunk_head = buff.substr(0, offset);
522 if(!get_len_from_chunk_head(chunk_head, chunk_size))
523 return false;
524
525 if(0 == chunk_size)
526 {
527 //Here is a small confusion
528 //In brief - if the chunk is the last one we need to get terminating sequence
529 //along with the cipher, generally in the "ddd\r\n\r\n" form
530
531 for(it++;it != buff.end(); it++)
532 {
533 if('\r' == *it)
534 continue;
535 else if('\n' == *it)
536 break;
537 else
538 {
539 LOG_ERROR("http_stream_filter: Wrong last chunk terminator");
540 return false;
541 }
542 }
543
544 if(it == buff.end())
545 return true;
546 }
547
548 buff.erase(buff.begin(), ++it);
549
550 is_matched = true;
551 return true;
552 }
553 else
554 return false;
555 }
556 }
557
558 return true;
559 }
560 //---------------------------------------------------------------------------
561 inline
562 bool handle_body_body_chunked(std::string& recv_buff, bool& need_more_data)
563 {
565 if(!recv_buff.size())
566 {
567 MERROR("Warning: CHUNKED mode, but connection unexpectedly closed");
569 return true;
570 }
571 m_chunked_cache += recv_buff;
572 recv_buff.clear();
573 bool is_matched = false;
574
575 while(true)
576 {
577 if(!m_chunked_cache.size())
578 {
579 need_more_data = true;
580 break;
581 }
582
583 switch(m_chunked_state)
584 {
586 if(m_chunked_cache[0] == '\n' || m_chunked_cache[0] == '\r')
587 {
588 //optimize a bit
589 if(m_chunked_cache[0] == '\r' && m_chunked_cache.size()>1 && m_chunked_cache[1] == '\n')
590 m_chunked_cache.erase(0, 2);
591 else
592 m_chunked_cache.erase(0, 1);
593 break;
594 }
596 {
597 LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head (" << m_chunked_cache.size() << " bytes)");
599 return false;
600 }
601
602 if(!is_matched)
603 {
604 need_more_data = true;
605 return true;
606 }else
607 {
609 if(m_len_in_remain == 0)
610 {//last chunk, let stop the stream and fix the chunk queue.
612 return true;
613 }
615 break;
616 }
617 break;
619 {
620 std::string chunk_body;
621 if(m_len_in_remain >= m_chunked_cache.size())
622 {
624 chunk_body.swap(m_chunked_cache);
625 }else
626 {
627 chunk_body.assign(m_chunked_cache, 0, m_len_in_remain);
629 m_len_in_remain = 0;
630 }
631
632 if (!m_pcontent_encoding_handler->update_in(chunk_body))
633 {
635 return false;
636 }
637
638 if(!m_len_in_remain)
640 }
641 break;
644 return true;
646 default:
647 LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state" << m_chunked_state);
648 return false;
649 }
650 }
651
652 return true;
653 }
654 //---------------------------------------------------------------------------
655 inline bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process)
656 {
657 MTRACE("http_stream_filter::parse_cached_header(*)");
658
659 size_t cur = 0;
660 while(cur < m_cache_to_process.size())
661 {
662 const size_t line_end = m_cache_to_process.find('\n', cur);
663 CHECK_AND_ASSERT_MES(line_end != std::string::npos, false, "http_stream_filter::parse_cached_header() invalid header (" << m_cache_to_process.size() << " bytes)");
664
665 boost::string_view line(m_cache_to_process.data() + cur, line_end - cur);
666 cur = line_end + 1;
667
668 if(line == "\r" || line.empty())
669 break;
670
671 boost::string_view name;
672 boost::string_view value;
673 CHECK_AND_ASSERT_MES(detail::parse_header_line(line, name, value), false, "http_stream_filter::parse_cached_header() invalid header (" << m_cache_to_process.size() << " bytes)");
674
675 std::string key(name.data(), name.size());
676 std::string val(value.data(), value.size());
677 if (!string_tools::compare_no_case(key, "Connection"))
678 body_info.m_connection = std::move(val);
679 else if(!string_tools::compare_no_case(key, "Referer"))
680 body_info.m_referer = std::move(val);
681 else if(!string_tools::compare_no_case(key, "Content-Length"))
682 body_info.m_content_length = std::move(val);
683 else if(!string_tools::compare_no_case(key, "Content-Type"))
684 body_info.m_content_type = std::move(val);
685 else if(!string_tools::compare_no_case(key, "Transfer-Encoding"))
686 body_info.m_transfer_encoding = std::move(val);
687 else if(!string_tools::compare_no_case(key, "Content-Encoding"))
688 body_info.m_content_encoding = std::move(val);
689 else if(!string_tools::compare_no_case(key, "Host"))
690 body_info.m_host = std::move(val);
691 else if(!string_tools::compare_no_case(key, "Cookie"))
692 body_info.m_cookie = std::move(val);
693 else if(!string_tools::compare_no_case(key, "User-Agent"))
694 body_info.m_user_agent = std::move(val);
695 else if(!string_tools::compare_no_case(key, "Origin"))
696 body_info.m_origin = std::move(val);
697 else
698 body_info.m_etc_fields.emplace_back(std::move(key), std::move(val));
699 }
700 return true;
701 }
702 //---------------------------------------------------------------------------
704 {
705 //First line response, look like this: "HTTP/1.1 200 OK"
706 const char *ptr = m_header_cache.c_str();
707 CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
708 ptr += 5;
709 CHECK_AND_ASSERT_MES(epee::misc_utils::parse::isdigit(*ptr), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
710 unsigned long ul;
711 char *end;
712 ul = strtoul(ptr, &end, 10);
713 CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end =='.', false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
715 ptr = end + 1;
716 CHECK_AND_ASSERT_MES(epee::misc_utils::parse::isdigit(*ptr), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
717 ul = strtoul(ptr, &end, 10);
718 CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
720 ptr = end + 1;
721 while (isblank(*ptr))
722 ++ptr;
723 CHECK_AND_ASSERT_MES(epee::misc_utils::parse::isdigit(*ptr), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
724 ul = strtoul(ptr, &end, 10);
725 CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
727 ptr = end;
728 // ignore the optional text, till the end
729 while (*ptr != '\r' && *ptr != '\n')
730 ++ptr;
731 if (*ptr == '\r')
732 ++ptr;
733 CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line (" << m_header_cache.size() << " header bytes)");
734 ++ptr;
735
736 m_header_cache.erase(0, ptr - m_header_cache.c_str());
737 return true;
738 }
739 inline
741 {
742 STATIC_REGEXP_EXPR_1(rexp_match_gzip, "^.*?((gzip)|(deflate))", boost::regex::icase | boost::regex::normal);
743 boost::smatch result; // 12 3
744 if(boost::regex_search( m_response_info.m_header_info.m_content_encoding, result, rexp_match_gzip, boost::match_default) && result[0].matched)
745 {
747 LOG_ERROR("GZIP encoding not supported");
748 return false;
749 }
750 else
751 {
753 }
754
755 return true;
756 }
757 inline
759 {
762 std::string fake_str; //gcc error workaround
763
765 CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header (" << m_header_cache.size() << " bytes)");
766
768
770 bool content_len_valid = false;
773
774
775
779 {//There will be no response body, server will display the local page with error
781 return true;
783 {
786 {
787 LOG_ERROR("Wrong Transfer-Encoding (" << m_response_info.m_header_info.m_transfer_encoding.size() << " bytes)");
789 return false;
790 }
793 return true;
794 }
796 {
797 //In the response header the length was specified
798 if(!content_len_valid)
799 {
800 LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght() (" << m_response_info.m_header_info.m_content_length.size() << " bytes)");
802 return false;
803 }
805 {
807 return true;
808 }
809 else
810 {
813 return true;
814 }
816 { //By indirect signs we suspect that data transfer will end with a connection break
819 {
821 LOG_ERROR("Unsupported MULTIPART BODY.");
822 return false;
823 }else
824 { //Apparently there are no signs of the form of transfer, will receive data until the connection is closed
826 MERROR("Undefined transfer type, consider http_body_transfer_connection_close method (" << m_header_cache.size() << " header bytes)");
827 return false;
828 }
829 return false;
830 }
831 inline
832 bool is_connection_close_field(const std::string& str)
833 {
834 STATIC_REGEXP_EXPR_1(rexp_match_close, "^\\s*close", boost::regex::icase | boost::regex::normal);
835 boost::smatch result;
836 if(boost::regex_search( str, result, rexp_match_close, boost::match_default) && result[0].matched)
837 return true;
838 else
839 return false;
840 }
841 inline
842 bool is_multipart_body(const http_header_info& head_info, OUT std::string& boundary)
843 {
844 //Check whether this is multi part - if yes, capture boundary immediately
845 STATIC_REGEXP_EXPR_1(rexp_match_multipart_type, "^\\s*multipart/([\\w\\-]+); boundary=((\"(.*?)\")|(\\\\\"(.*?)\\\\\")|([^\\s;]*))", boost::regex::icase | boost::regex::normal);
846 boost::smatch result;
847 if(boost::regex_search(head_info.m_content_type, result, rexp_match_multipart_type, boost::match_default) && result[0].matched)
848 {
849 if(result[4].matched)
850 boundary = result[4];
851 else if(result[6].matched)
852 boundary = result[6];
853 else if(result[7].matched)
854 boundary = result[7];
855 else
856 {
857 LOG_ERROR("Failed to match boundary in content-type (" << head_info.m_content_type.size() << " bytes)");
858 return false;
859 }
860 return true;
861 }
862 else
863 return false;
864
865 return true;
866 }
867 };
869 }
870}
871}
#define s(x, c)
Definition aesb.c:47
Definition syncobj.h:82
do_nothing_sub_handler(i_target_handler *powner_filter)
Definition http_client_base.h:63
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
status handle_401(const http_response_info &response)
Definition http_auth.h:143
@ kSuccess
Definition http_auth.h:97
@ kParseFailure
Definition http_auth.h:97
@ kBadPassword
Definition http_auth.h:97
boost::optional< std::pair< std::string, std::string > > get_auth_field(const boost::string_ref method, const boost::string_ref uri)
Definition http_auth.h:157
void set_connector(F connector)
Definition http_client.h:186
void set_auto_connect(bool auto_connect) override
Definition http_client.h:180
bool set_reply_content_encoder()
Definition http_client.h:740
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 shutdown() override
Definition http_client.h:204
bool is_multipart_body(const http_header_info &head_info, OUT std::string &boundary)
Definition http_client.h:842
virtual bool handle_target_data(std::string &piece_of_transfer) override
Definition http_client.h:215
bool handle_body_connection_close(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:470
bool is_connected(bool *ssl=NULL) override
Definition http_client.h:209
bool test(const std::string &s, std::chrono::milliseconds timeout)
Definition http_client.h:314
bool connect(std::chrono::milliseconds timeout) override
Definition http_client.h:192
bool parse_header(http_header_info &body_info, const std::string &m_cache_to_process)
Definition http_client.h:655
bool handle_body_content_len(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:444
void wipe_response()
Definition http_client.h:332
bool get_len_from_chunk_head(const std::string &chunk_head, size_t &result_size)
Definition http_client.h:495
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:228
bool handle_body_body_chunked(std::string &recv_buff, bool &need_more_data)
Definition http_client.h:562
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:308
uint64_t get_bytes_received() const override
Definition http_client.h:327
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:235
bool handle_reciev(std::chrono::milliseconds timeout)
Definition http_client.h:339
http_response_info m_response_info
Definition http_client.h:135
bool is_hex_symbol(char ch)
Definition http_client.h:485
reciev_machine_state m_state
Definition http_client.h:140
bool get_chunk_head(std::string &buff, size_t &chunk_size, bool &is_matched)
Definition http_client.h:506
reciev_machine_state
Definition http_client.h:111
const std::string & get_host() const
Definition http_client.h:165
virtual bool on_header(const http_response_info &headers)
Definition http_client.h:223
bool is_connection_close_field(const std::string &str)
Definition http_client.h:832
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:403
uint64_t get_bytes_sent() const override
Definition http_client.h:322
bool analize_first_response_line()
Definition http_client.h:703
Definition net_ssl.h:78
#define true
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
bool parse_header_line(boost::string_view line, boost::string_view &name, boost::string_view &value)
Definition http_base.h:85
http_simple_client_template< blocked_mode_client > http_simple_client
Definition http_client.h:868
std::list< std::pair< std::string, std::string > > fields_list
Definition http_base.h:67
@ e_ssl_support_autodetect
Definition net_ssl.h:53
PUSH_WARNINGS bool get_xtype_from_string(OUT XType &val, const std::string &str_id)
Definition string_tools_lexical.h:45
bool compare_no_case(const std::string &str1, const std::string &str2)
Definition string_tools.cpp:136
std::string & trim(std::string &str)
Definition string_tools.h:75
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
Definition uri.py:1
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
#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
#define OUT
Definition string_tools.h:40
Definition http_base.h:121
fields_list m_etc_fields
Definition http_base.h:132
std::string m_content_length
Definition http_base.h:124
std::string m_content_encoding
Definition http_base.h:127
std::string m_origin
Definition http_base.h:131
std::string m_referer
Definition http_base.h:123
std::string m_cookie
Definition http_base.h:129
std::string m_connection
Definition http_base.h:122
std::string m_user_agent
Definition http_base.h:130
std::string m_content_type
Definition http_base.h:125
std::string m_transfer_encoding
Definition http_base.h:126
std::string m_host
Definition http_base.h:128
int m_http_ver_lo
Definition http_base.h:208
void clear()
Definition http_base.h:210
int m_http_ver_hi
Definition http_base.h:207
void wipe()
Definition http_base.h:216
int m_response_code
Definition http_base.h:201
http_header_info m_header_info
Definition http_base.h:206
std::string m_body
Definition http_base.h:204
Definition http_client_base.h:54
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153