From a7a861351f6c469bce6b587417a2cc3ac03658fc Mon Sep 17 00:00:00 2001 From: tastytea Date: Sat, 4 Jan 2020 18:11:24 +0100 Subject: [PATCH] Move low-level network stuff to CURLWrapper. --- include/curl_wrapper.hpp | 92 ++++++++++++++++++++++++++++++++++++++++ include/instance.hpp | 48 ++------------------- include/request.hpp | 16 ++++++- src/curl_wrapper.cpp | 90 +++++++++++++++++++++++++++++++++++++++ src/instance.cpp | 67 +---------------------------- src/request.cpp | 7 +++ 6 files changed, 208 insertions(+), 112 deletions(-) create mode 100644 include/curl_wrapper.hpp create mode 100644 src/curl_wrapper.cpp diff --git a/include/curl_wrapper.hpp b/include/curl_wrapper.hpp new file mode 100644 index 0000000..328c3b9 --- /dev/null +++ b/include/curl_wrapper.hpp @@ -0,0 +1,92 @@ +/* This file is part of mastodonpp. + * Copyright © 2020 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef MASTODONPP_CURL_WRAPPER_HPP +#define MASTODONPP_CURL_WRAPPER_HPP + +#include "curl/curl.h" + +#include + +namespace mastodonpp +{ + +using std::string; + +//! Internal use only. +extern bool curl_initialized; + +/*! + * @brief Handles the details of network connections. + * + * @since 0.1.0 + * + * @headerfile curl_wrapper.hpp mastodonpp/curl_wrapper.hpp + */ +class CURLWrapper +{ +public: + /*! + * @brief Constructs a CURLWrapper object. + * + * The first construction of an CurlWrapper object will call + * `curl_global_init`, which is not thread-safe. For more information + * consult [curl_global_init(3)] + * (https://curl.haxx.se/libcurl/c/curl_global_init.html). + * + * @since 0.1.0 + */ + CURLWrapper(); + + //! Copy constructor + CURLWrapper(const CURLWrapper &other) = default; + + //! Move constructor + CURLWrapper(CURLWrapper &&other) noexcept = default; + + //! Destructor + virtual ~CURLWrapper() noexcept; + + //! Copy assignment operator + CURLWrapper& operator=(const CURLWrapper &other) = default; + + //! Move assignment operator + CURLWrapper& operator=(CURLWrapper &&other) noexcept = default; + +private: + CURL *_connection; + char _curl_buffer_error[CURL_ERROR_SIZE]; + string _curl_buffer; + + /*! + * @brief libcurl write callback function. + * + * @since 0.1.0 + */ + static int writer(char *data, size_t size, size_t nmemb, + string *writerData); + + /*! + * @brief Setup libcurl connection. + * + * @since 0.1.0 + */ + void setup_curl(); +}; + +} // namespace mastodonpp + +#endif // MASTODONPP_CURL_WRAPPER_HPP diff --git a/include/instance.hpp b/include/instance.hpp index 4feab15..5c62b7a 100644 --- a/include/instance.hpp +++ b/include/instance.hpp @@ -17,7 +17,7 @@ #ifndef MASTODONPP_INSTANCE_HPP #define MASTODONPP_INSTANCE_HPP -#include +#include "curl_wrapper.hpp" #include @@ -26,27 +26,19 @@ namespace mastodonpp using std::string; -//! Internal use only. -extern bool curl_initialized; - /*! - * @brief Holds the access data of and the connection to an instance. + * @brief Holds the access data of an instance. * * @since 0.1.0 * * @headerfile instance.hpp mastodonpp/instance.hpp */ -class Instance +class Instance : public CURLWrapper { public: /*! * @brief Construct a new Instance object. * - * The first construction of an Instance object will call - * `curl_global_init`, which is not thread-safe. For more information - * consult [curl_global_init(3)] - * (https://curl.haxx.se/libcurl/c/curl_global_init.html). - * * @param instance The hostname of the instance. * @param access_token Your access token. * @@ -54,43 +46,9 @@ public: */ explicit Instance(string instance, string access_token); - //! Copy constructor - Instance(const Instance &other) = default; - - //! Move constructor - Instance(Instance &&other) = default; - - //! Destructor - virtual ~Instance(); - - //! Copy assignment operator - Instance& operator=(const Instance &other) = delete; - - //! Move assignment operator - Instance& operator=(Instance &&other) = delete; - private: const string _instance; string _access_token; - CURL *_connection; - char _curl_buffer_error[CURL_ERROR_SIZE]; - string _curl_buffer; - - - /*! - * @brief libcurl write callback function. - * - * @since 0.1.0 - */ - static int writer(char *data, size_t size, size_t nmemb, - string *writerData); - - /*! - * @brief Setup libcurl connection. - * - * @since 0.1.0 - */ - void setup_curl(); }; } // namespace mastodonpp diff --git a/include/request.hpp b/include/request.hpp index dca8327..e35b85c 100644 --- a/include/request.hpp +++ b/include/request.hpp @@ -18,6 +18,7 @@ #define MASTODONPP_REQUEST_HPP #include "api.hpp" +#include "curl_wrapper.hpp" #include "instance.hpp" #include "return_types.hpp" @@ -35,7 +36,7 @@ using std::string; * * @headerfile request.hpp mastodonpp/request.hpp */ -class Request +class Request : public CURLWrapper { public: /*! @@ -50,11 +51,24 @@ public: /*! * @brief Make a HTTP GET call. * + * @param endpoint Endpoint as API::endpoint_type, for example: + * `mastodonpp::API::v1::instance`. + * * @since 0.1.0 */ [[nodiscard]] answer_type get(API::endpoint_type endpoint) const; + /*! + * @brief Make a HTTP GET call. + * + * @param endpoint Endpoint as string, for example: "/api/v1/instance". + * + * @since 0.1.0 + */ + [[nodiscard]] + answer_type get(string endpoint) const; + private: Instance &_instance; }; diff --git a/src/curl_wrapper.cpp b/src/curl_wrapper.cpp new file mode 100644 index 0000000..ef724b9 --- /dev/null +++ b/src/curl_wrapper.cpp @@ -0,0 +1,90 @@ +/* This file is part of mastodonpp. + * Copyright © 2020 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "curl_wrapper.hpp" +#include "exceptions.hpp" + +namespace mastodonpp +{ + +bool curl_initialized{false}; + +CURLWrapper::CURLWrapper() + : _curl_buffer_error{} +{ + if (!curl_initialized) + { + curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise) + curl_initialized = true; + } + _connection = curl_easy_init(); + setup_curl(); +} +CURLWrapper::~CURLWrapper() noexcept +{ + curl_easy_cleanup(_connection); + + if (curl_initialized) + { + curl_global_cleanup(); + curl_initialized = false; + } +} + +int CURLWrapper::writer(char *data, size_t size, size_t nmemb, string *writerData) +{ + if(writerData == nullptr) + { + return 0; + } + + writerData->append(data, size*nmemb); + + return static_cast(size * nmemb); +} + +void CURLWrapper::setup_curl() +{ + if (_connection == nullptr) + { + throw CURLException{CURLE_FAILED_INIT, "Failed to initialize curl."}; + } + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + CURLcode code{curl_easy_setopt(_connection, CURLOPT_ERRORBUFFER, + _curl_buffer_error)}; + if (code != CURLE_OK) + { + throw CURLException{code, "Failed to set error buffer."}; + } + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + code = curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer); + if (code != CURLE_OK) + { + throw CURLException{code, "Failed to set writer", _curl_buffer_error}; + } + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + code = curl_easy_setopt(_connection, CURLOPT_WRITEDATA, &_curl_buffer); + if (code != CURLE_OK) + { + throw CURLException{code, "Failed to set write data", + _curl_buffer_error}; + } +} + +} // namespace mastodonpp diff --git a/src/instance.cpp b/src/instance.cpp index 3f6ab1b..6b3443d 100644 --- a/src/instance.cpp +++ b/src/instance.cpp @@ -15,7 +15,6 @@ */ #include "instance.hpp" -#include "exceptions.hpp" #include @@ -24,73 +23,9 @@ namespace mastodonpp using std::move; -bool curl_initialized{false}; - Instance::Instance(string instance, string access_token) : _instance{move(instance)} , _access_token{move(access_token)} - , _curl_buffer_error{} -{ - if (!curl_initialized) - { - curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise) - curl_initialized = true; - } - _connection = curl_easy_init(); - setup_curl(); -} -Instance::~Instance() -{ - curl_easy_cleanup(_connection); - - if (curl_initialized) - { - curl_global_cleanup(); - curl_initialized = false; - } -} - -int Instance::writer(char *data, size_t size, size_t nmemb, string *writerData) -{ - if(writerData == nullptr) - { - return 0; - } - - writerData->append(data, size*nmemb); - - return static_cast(size * nmemb); -} - -void Instance::setup_curl() -{ - if (_connection == nullptr) - { - throw CURLException{CURLE_FAILED_INIT, "Failed to initialize curl."}; - } - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - CURLcode code{curl_easy_setopt(_connection, CURLOPT_ERRORBUFFER, - _curl_buffer_error)}; - if (code != CURLE_OK) - { - throw CURLException{code, "Failed to set error buffer."}; - } - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - code = curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer); - if (code != CURLE_OK) - { - throw CURLException{code, "Failed to set writer", _curl_buffer_error}; - } - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - code = curl_easy_setopt(_connection, CURLOPT_WRITEDATA, &_curl_buffer); - if (code != CURLE_OK) - { - throw CURLException{code, "Failed to set write data", - _curl_buffer_error}; - } -} +{} } // namespace mastodonpp diff --git a/src/request.cpp b/src/request.cpp index e2ad4be..cf2eb39 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -30,4 +30,11 @@ answer_type Request::get(API::endpoint_type endpoint) const return answer; } +answer_type Request::get(string endpoint) const +{ + answer_type answer; + answer.body = endpoint; + return answer; +} + } // namespace mastodonpp