Advertisement
Guest User

Untitled

a guest
Jan 1st, 2022
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.37 KB | None | 0 0
  1. #include <iostream>
  2. #include <istream>
  3. #include <ostream>
  4. #include <string>
  5. #include <boost/asio.hpp>
  6. #include <boost/bind/bind.hpp>
  7. #define BOOST_THREAD_PROVIDES_FUTURE
  8. #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
  9. #define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
  10. #include <boost/thread.hpp>
  11.  
  12. using boost::asio::ip::tcp;
  13.  
  14. class client
  15. {
  16. public:
  17. client(boost::asio::io_service& io_service,
  18. const std::string& server, const std::string& path)
  19. : resolver_(io_service),
  20. socket_(io_service), url(server)
  21. {
  22. // Form the request. We specify the "Connection: close" header so that the
  23. // server will close the socket after transmitting the response. This will
  24. // allow us to treat all data up until the EOF as the content.
  25. std::ostream request_stream(&request_);
  26. request_stream << "GET " << path << " HTTP/1.0\r\n";
  27. request_stream << "Host: " << server << "\r\n";
  28. request_stream << "Accept: */*\r\n";
  29. request_stream << "Connection: close\r\n\r\n";
  30.  
  31. // Start an asynchronous resolve to translate the server and service names
  32. // into a list of endpoints.
  33. resolver_.async_resolve(server, "6969",
  34. boost::bind(&client::handle_resolve, this,
  35. boost::asio::placeholders::error,
  36. boost::asio::placeholders::results));
  37. }
  38.  
  39. boost::future<std::string> GetResponse() {
  40. return promise_resp.get_future();
  41. }
  42.  
  43. private:
  44. void handle_resolve(const boost::system::error_code& err,
  45. const tcp::resolver::results_type& endpoints)
  46. {
  47. if (!err)
  48. {
  49. // Attempt a connection to each endpoint in the list until we
  50. // successfully establish a connection.
  51. boost::asio::async_connect(socket_, endpoints,
  52. boost::bind(&client::handle_connect, this,
  53. boost::asio::placeholders::error));
  54. }
  55. else
  56. {
  57. SetException("Error resolve: " + err.message() + "\n");
  58. }
  59. }
  60.  
  61. void handle_connect(const boost::system::error_code& err)
  62. {
  63. if (!err)
  64. {
  65. // The connection was successful. Send the request.
  66. boost::asio::async_write(socket_, request_,
  67. boost::bind(&client::handle_write_request, this,
  68. boost::asio::placeholders::error));
  69. }
  70. else
  71. {
  72. SetException("Error connect: " + err.message() + "\n");
  73. }
  74. }
  75.  
  76. void handle_write_request(const boost::system::error_code& err)
  77. {
  78. if (!err)
  79. {
  80. // Read the response status line. The response_ streambuf will
  81. // automatically grow to accommodate the entire line. The growth may be
  82. // limited by passing a maximum size to the streambuf constructor.
  83. boost::asio::async_read_until(socket_, response_, "\r\n",
  84. boost::bind(&client::handle_read_status_line, this,
  85. boost::asio::placeholders::error));
  86. }
  87. else
  88. {
  89. SetException("Error request: " + err.message() + "\n");
  90. }
  91. }
  92.  
  93. void handle_read_status_line(const boost::system::error_code& err)
  94. {
  95. if (!err)
  96. {
  97. // Check that response is OK.
  98. std::istream response_stream(&response_);
  99. std::string http_version;
  100. response_stream >> http_version;
  101. unsigned int status_code;
  102. response_stream >> status_code;
  103. std::string status_message;
  104. std::getline(response_stream, status_message);
  105. if (!response_stream || http_version.substr(0, 5) != "HTTP/")
  106. {
  107. SetException("Invalid response\n");
  108. return;
  109. }
  110. if (status_code != 200)
  111. {
  112. SetException("Response returned with status code " + std::to_string(status_code) + "\n");
  113. return;
  114. }
  115.  
  116. // Read the response headers, which are terminated by a blank line.
  117. boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
  118. boost::bind(&client::handle_read_headers, this,
  119. boost::asio::placeholders::error));
  120. }
  121. else
  122. {
  123. SetException("Error status line: " + err.message() + "\n");
  124. }
  125. }
  126.  
  127. void handle_read_headers(const boost::system::error_code& err)
  128. {
  129. if (!err)
  130. {
  131. // Start reading remaining data until EOF.
  132. boost::asio::async_read(socket_, response_,
  133. boost::asio::transfer_at_least(1),
  134. boost::bind(&client::handle_read_content, this,
  135. boost::asio::placeholders::error));
  136. }
  137. else
  138. {
  139. SetException("Error head: " + err.message() +"\n");
  140. }
  141. }
  142.  
  143. void handle_read_content(const boost::system::error_code& err)
  144. {
  145. if (!err)
  146. {
  147. // Continue reading remaining data until EOF.
  148. boost::asio::async_read(socket_, response_,
  149. boost::asio::transfer_at_least(1),
  150. boost::bind(&client::handle_read_content, this,
  151. boost::asio::placeholders::error));
  152. }
  153. else if (err == boost::asio::error::eof) {
  154. SetResponse();
  155. }
  156. else
  157. {
  158. SetException("Error content: " + err.message() + "\n");
  159. }
  160. }
  161.  
  162. void SetResponse() {
  163. std::istream response_stream(&response_);
  164. std::string response_str {std::istreambuf_iterator<char>(response_stream),
  165. std::istreambuf_iterator<char>()};
  166. promise_resp.set_value(response_str);
  167. }
  168. void SetException(std::string const & excp){
  169. std::logic_error le (excp);
  170. promise_resp.set_exception(std::move(le));
  171. }
  172.  
  173. tcp::resolver resolver_;
  174. tcp::socket socket_;
  175. boost::asio::streambuf request_;
  176. boost::asio::streambuf response_;
  177.  
  178. boost::promise<std::string> promise_resp;
  179.  
  180. std::string url;
  181. };
  182.  
  183. int main()
  184. {
  185. SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
  186. try
  187. {
  188. boost::asio::io_service io_service;
  189.  
  190. std::stringstream input {
  191. "pubt.net\n"
  192. "210.244.71.25\n"
  193. "tracker.dler.org\n"
  194. "125.227.35.196\n"
  195. "retracker.local\n"
  196. "tracker2.wasabii.com.tw\n"
  197. "tracker.filetracker.pl\n"
  198. "46.4.109.148\n"
  199. "87.248.186.252\n"
  200. "tracker.grepler.com\n"
  201. "tracker.tiny-vps.com"
  202. };
  203. std::string request_str = "/announce?info_hash=%AFWo%87r%DA%82%B7%F5%8B%B6%21%1C%2AF%3B%F8%7BV%20";
  204.  
  205. std::vector<std::shared_ptr<client>> urls;
  206. std::string line;
  207. while (std::getline(input, line)) {
  208. urls.push_back(std::make_shared<client>(io_service, line, request_str));
  209. }
  210.  
  211. std::vector<boost::future<std::string>> results;
  212. for (auto &el: urls) {
  213. results.push_back(el->GetResponse());
  214. }
  215. std::thread t([&] { SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); io_service.run();});
  216.  
  217. boost::promise<std::string> any_res;
  218. struct DoneCheck {
  219. private:
  220. boost::promise<std::string> & result;
  221. boost::asio::io_service & service;
  222. public:
  223. DoneCheck(boost::promise<std::string> & r, boost::asio::io_service & serv) : result(r), service(serv) {};
  224. void operator()(boost::future<std::vector<boost::future<std::string>>> result_args) {
  225. auto results = result_args.get();
  226. auto any_res = results.begin();
  227. try {
  228. result.set_value(any_res->get()); // << тут надолго останавливается работа
  229. service.dispatch([&]{service.stop(); service.reset();});
  230. } catch (std::exception & excep) {
  231. results.erase(results.begin(), results.begin() + 1);
  232. if (!results.empty())
  233. boost::when_any(results.begin(), results.end())
  234. .then(std::move(*this));
  235. else { result.set_exception(excep); }
  236. }
  237. }
  238. };
  239. boost::when_any(results.begin(), results.end())
  240. .then(DoneCheck{any_res, io_service});
  241.  
  242. try {
  243. std::cout << any_res.get_future().get() << std::endl;
  244. } catch (std::exception &excp) {
  245. std::cerr << excp.what() << std::endl;
  246. }
  247.  
  248. t.join();
  249. }
  250. catch (std::exception& e)
  251. {
  252. std::cout << "Exception: " << e.what() << "\n";
  253. }
  254.  
  255. return 0;
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement