replaced boost::asio with curlpp
This commit is contained in:
parent
0fe04040a7
commit
bf6c5df56f
|
@ -2,11 +2,16 @@ cmake_minimum_required (VERSION 3.7)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
project (rss2mastodon
|
project (rss2mastodon
|
||||||
VERSION 0.1.8
|
VERSION 0.2.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall")
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
include(FindCURL)
|
||||||
|
find_package(CURL REQUIRED)
|
||||||
|
|
||||||
add_executable(rss2mastodon src/rss2mastodon.cpp src/http.cpp)
|
add_executable(rss2mastodon src/rss2mastodon.cpp src/http.cpp)
|
||||||
target_link_libraries(rss2mastodon mastodon-cpp boost_system boost_filesystem ssl crypto pthread)
|
target_link_libraries(rss2mastodon mastodon-cpp boost_system boost_filesystem ssl crypto ${CURL_LIBRARIES} curlpp)
|
||||||
install(TARGETS rss2mastodon DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS rss2mastodon DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
|
@ -10,6 +10,8 @@ Use at your own risk.
|
||||||
* C++ compiler (tested: gcc 6.4, clang 5.0)
|
* C++ compiler (tested: gcc 6.4, clang 5.0)
|
||||||
* [cmake](https://cmake.org/) (tested: 3.9.6)
|
* [cmake](https://cmake.org/) (tested: 3.9.6)
|
||||||
* [boost](http://www.boost.org/) (tested: 1.63.0)
|
* [boost](http://www.boost.org/) (tested: 1.63.0)
|
||||||
|
* [libcurl](https://curl.haxx.se/) (tested: 7.58.0)
|
||||||
|
* [curlpp](http://www.curlpp.org/) (tested: 0.8.1)
|
||||||
* [mastodon-cpp](https://github.com/tastytea/mastodon-cpp) (at least: 0.2.0)
|
* [mastodon-cpp](https://github.com/tastytea/mastodon-cpp) (at least: 0.2.0)
|
||||||
|
|
||||||
## Get sourcecode
|
## Get sourcecode
|
||||||
|
|
136
src/http.cpp
136
src/http.cpp
|
@ -20,133 +20,43 @@
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <boost/asio.hpp>
|
#include <curlpp/cURLpp.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
#include <curlpp/Easy.hpp>
|
||||||
|
#include <curlpp/Options.hpp>
|
||||||
|
#include <curlpp/Exception.hpp>
|
||||||
#include "rss2mastodon.hpp"
|
#include "rss2mastodon.hpp"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
|
|
||||||
using boost::asio::ip::tcp;
|
namespace curlopts = curlpp::options;
|
||||||
namespace ssl = boost::asio::ssl;
|
|
||||||
typedef ssl::stream<tcp::socket> ssl_socket;
|
|
||||||
|
|
||||||
const std::uint16_t http_get(const string &host, const string &path, string &answer, const string &useragent)
|
const std::uint16_t http_get(const string &feedurl, string &answer, const string &useragent)
|
||||||
{
|
{
|
||||||
ssl::context ctx(ssl::context::tlsv12);
|
|
||||||
boost::asio::io_service io_service;
|
|
||||||
tcp::resolver resolver(io_service);
|
|
||||||
ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, ctx);
|
|
||||||
|
|
||||||
ctx.set_options(ssl::context::tlsv12 | ssl::context::tlsv11 |
|
|
||||||
ssl::context::no_sslv3 | ssl::context::no_sslv2 |
|
|
||||||
ssl::context::no_tlsv1);
|
|
||||||
ctx.set_default_verify_paths();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tcp::resolver::query query(host, "https");
|
|
||||||
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
|
|
||||||
boost::asio::connect(socket.lowest_layer(), endpoint_iterator);
|
|
||||||
socket.lowest_layer().set_option(tcp::no_delay(true));
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: " << e.what() << "\n";
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Server Name Indication (SNI)
|
|
||||||
SSL_set_tlsext_host_name(socket.native_handle(), host.c_str());
|
|
||||||
|
|
||||||
socket.set_verify_mode(ssl::verify_peer);
|
|
||||||
socket.set_verify_callback(ssl::rfc2818_verification(host));
|
|
||||||
|
|
||||||
socket.handshake(ssl_socket::client);
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: " << e.what() << "\n";
|
|
||||||
return 17;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
boost::asio::streambuf request;
|
|
||||||
std::ostream request_stream(&request);
|
|
||||||
request_stream << "GET " << path;
|
|
||||||
request_stream << " HTTP/1.0\r\n";
|
|
||||||
request_stream << "Host: " << host << "\r\n";
|
|
||||||
request_stream << "Accept: */*\r\n";
|
|
||||||
request_stream << "Connection: close\r\n";
|
|
||||||
if (useragent.empty())
|
|
||||||
{
|
|
||||||
request_stream << "\r\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
request_stream << "User-Agent: " << useragent << "\r\n\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::write(socket, request);
|
|
||||||
|
|
||||||
boost::asio::streambuf response;
|
|
||||||
boost::asio::read_until(socket, response, "\r\n");
|
|
||||||
|
|
||||||
// Check that response is OK.
|
|
||||||
std::istream response_stream(&response);
|
|
||||||
std::string http_version;
|
|
||||||
std::uint16_t status_code;
|
|
||||||
std::string status_message;
|
|
||||||
response_stream >> http_version;
|
|
||||||
response_stream >> status_code;
|
|
||||||
std::getline(response_stream, status_message);
|
|
||||||
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
|
|
||||||
{
|
|
||||||
cerr << "ERROR: Invalid response from server\n";
|
|
||||||
cerr << "Response was: " << http_version << " " << status_code
|
|
||||||
<< " " << status_message << '\n';
|
|
||||||
return 18;
|
|
||||||
}
|
|
||||||
if (status_code != 200)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: Response returned with status code "
|
|
||||||
<< status_code << ": " << status_message << "\n";
|
|
||||||
return status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read headers
|
|
||||||
boost::asio::read_until(socket, response, "\r\n\r\n");
|
|
||||||
std::string header;
|
|
||||||
// cerr << "Header: \n";
|
|
||||||
while (std::getline(response_stream, header) && header != "\r")
|
|
||||||
{
|
|
||||||
// cerr << header << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read body
|
|
||||||
boost::system::error_code error;
|
|
||||||
answer = "";
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
while (boost::asio::read(socket, response,
|
curlpp::Easy request;
|
||||||
boost::asio::transfer_at_least(1), error))
|
request.setOpt<curlopts::Url>(feedurl);
|
||||||
|
request.setOpt<curlopts::UserAgent>(useragent);
|
||||||
|
request.setOpt<curlopts::HttpHeader>(
|
||||||
{
|
{
|
||||||
oss << &response;
|
"Connection: close",
|
||||||
}
|
});
|
||||||
if (error != boost::asio::error::eof)
|
|
||||||
{
|
oss << request;
|
||||||
// TODO: Find out why the "short read" error occurs
|
|
||||||
//throw boost::system::system_error(error);
|
|
||||||
//cerr << "ERROR: " << error.message() << '\n';
|
|
||||||
}
|
|
||||||
answer = oss.str();
|
answer = oss.str();
|
||||||
//cerr << "Answer from server: " << oss.str() << '\n';
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (curlpp::RuntimeError &e)
|
||||||
{
|
{
|
||||||
cerr << "Exception: " << e.what() << "\n";
|
cerr << "RUNTIME ERROR: " << e.what() << std::endl;
|
||||||
|
return 0xffff;
|
||||||
|
}
|
||||||
|
catch (curlpp::LogicError &e)
|
||||||
|
{
|
||||||
|
cerr << "LOGIC ERROR: " << e.what() << std::endl;
|
||||||
return 0xffff;
|
return 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,16 +201,12 @@ int main(int argc, char *argv[])
|
||||||
std::uint16_t ret;
|
std::uint16_t ret;
|
||||||
|
|
||||||
read_config(config, profile, instance, access_token, feedurl);
|
read_config(config, profile, instance, access_token, feedurl);
|
||||||
std::size_t pos = 0;
|
|
||||||
pos = feedurl.find("//") + 2;
|
|
||||||
const string hostname = feedurl.substr(pos, feedurl.find('/', pos) - pos);
|
|
||||||
const string path = feedurl.substr(pos + hostname.size());
|
|
||||||
|
|
||||||
string answer;
|
string answer;
|
||||||
string last_entry = config.get(profile + ".last_entry", "");
|
string last_entry = config.get(profile + ".last_entry", "");
|
||||||
std::vector<string> entries;
|
std::vector<string> entries;
|
||||||
//FIXME: User-Agent
|
//FIXME: User-Agent
|
||||||
ret = http_get(hostname, path, answer, "rss2mastodon/experimental");
|
ret = http_get(feedurl, answer, "rss2mastodon/experimental");
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -13,7 +13,7 @@ void read_config(pt::ptree &config, const string &profile, string &instance, str
|
||||||
std::vector<string> parse_website(const string &profile, const string &xml);
|
std::vector<string> parse_website(const string &profile, const string &xml);
|
||||||
|
|
||||||
// http.cpp
|
// http.cpp
|
||||||
const std::uint16_t http_get(const string &host, const string &path,
|
const std::uint16_t http_get(const string &feedurl,
|
||||||
string &answer, const string &useragent = "");
|
string &answer, const string &useragent = "");
|
||||||
|
|
||||||
#endif // RSS2MASTODON_HPP
|
#endif // RSS2MASTODON_HPP
|
||||||
|
|
Loading…
Reference in New Issue
Block a user