input/curl: wrap CURLM* in new class CurlMulti
This commit is contained in:
parent
7063c423eb
commit
fc83d38e67
@ -1277,6 +1277,7 @@ libinput_a_SOURCES += \
|
||||
src/input/IcyInputStream.cxx src/input/IcyInputStream.hxx \
|
||||
src/input/plugins/CurlInputPlugin.cxx src/input/plugins/CurlInputPlugin.hxx \
|
||||
src/lib/curl/Easy.hxx \
|
||||
src/lib/curl/Multi.hxx \
|
||||
src/IcyMetaDataParser.cxx src/IcyMetaDataParser.hxx
|
||||
endif
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
#include "CurlInputPlugin.hxx"
|
||||
#include "lib/curl/Easy.hxx"
|
||||
#include "lib/curl/Multi.hxx"
|
||||
#include "../AsyncInputStream.hxx"
|
||||
#include "../IcyInputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
@ -194,14 +195,10 @@ private:
|
||||
* Manager for the global CURLM object.
|
||||
*/
|
||||
class CurlGlobal final : private TimeoutMonitor {
|
||||
CURLM *const multi;
|
||||
CurlMulti multi;
|
||||
|
||||
public:
|
||||
CurlGlobal(EventLoop &_loop, CURLM *_multi);
|
||||
|
||||
~CurlGlobal() {
|
||||
curl_multi_cleanup(multi);
|
||||
}
|
||||
explicit CurlGlobal(EventLoop &_loop);
|
||||
|
||||
void Add(CurlInputStream *c);
|
||||
void Remove(CurlInputStream *c);
|
||||
@ -214,7 +211,7 @@ public:
|
||||
void ReadInfo();
|
||||
|
||||
void Assign(curl_socket_t fd, CurlSocket &cs) {
|
||||
curl_multi_assign(multi, fd, &cs);
|
||||
curl_multi_assign(multi.Get(), fd, &cs);
|
||||
}
|
||||
|
||||
void SocketAction(curl_socket_t fd, int ev_bitmask);
|
||||
@ -230,7 +227,7 @@ public:
|
||||
*/
|
||||
void ResumeSockets() {
|
||||
int running_handles;
|
||||
curl_multi_socket_all(multi, &running_handles);
|
||||
curl_multi_socket_all(multi.Get(), &running_handles);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -258,15 +255,14 @@ static CurlGlobal *curl_global;
|
||||
static constexpr Domain curl_domain("curl");
|
||||
static constexpr Domain curlm_domain("curlm");
|
||||
|
||||
CurlGlobal::CurlGlobal(EventLoop &_loop, CURLM *_mutex)
|
||||
:TimeoutMonitor(_loop), multi(_mutex)
|
||||
CurlGlobal::CurlGlobal(EventLoop &_loop)
|
||||
:TimeoutMonitor(_loop)
|
||||
{
|
||||
curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION,
|
||||
CurlSocket::SocketFunction);
|
||||
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, this);
|
||||
multi.SetOption(CURLMOPT_SOCKETFUNCTION, CurlSocket::SocketFunction);
|
||||
multi.SetOption(CURLMOPT_SOCKETDATA, this);
|
||||
|
||||
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, TimerFunction);
|
||||
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, this);
|
||||
multi.SetOption(CURLMOPT_TIMERFUNCTION, TimerFunction);
|
||||
multi.SetOption(CURLMOPT_TIMERDATA, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,7 +362,7 @@ CurlGlobal::Add(CurlInputStream *c)
|
||||
assert(c != nullptr);
|
||||
assert(c->easy);
|
||||
|
||||
CURLMcode mcode = curl_multi_add_handle(multi, c->easy.Get());
|
||||
CURLMcode mcode = curl_multi_add_handle(multi.Get(), c->easy.Get());
|
||||
if (mcode != CURLM_OK)
|
||||
throw FormatRuntimeError("curl_multi_add_handle() failed: %s",
|
||||
curl_multi_strerror(mcode));
|
||||
@ -394,7 +390,7 @@ input_curl_easy_add_indirect(CurlInputStream *c)
|
||||
inline void
|
||||
CurlGlobal::Remove(CurlInputStream *c)
|
||||
{
|
||||
curl_multi_remove_handle(multi, c->easy.Get());
|
||||
curl_multi_remove_handle(multi.Get(), c->easy.Get());
|
||||
}
|
||||
|
||||
void
|
||||
@ -467,7 +463,7 @@ void
|
||||
CurlGlobal::SocketAction(curl_socket_t fd, int ev_bitmask)
|
||||
{
|
||||
int running_handles;
|
||||
CURLMcode mcode = curl_multi_socket_action(multi, fd, ev_bitmask,
|
||||
CURLMcode mcode = curl_multi_socket_action(multi.Get(), fd, ev_bitmask,
|
||||
&running_handles);
|
||||
if (mcode != CURLM_OK)
|
||||
FormatError(curlm_domain,
|
||||
@ -490,7 +486,7 @@ CurlGlobal::ReadInfo()
|
||||
CURLMsg *msg;
|
||||
int msgs_in_queue;
|
||||
|
||||
while ((msg = curl_multi_info_read(multi,
|
||||
while ((msg = curl_multi_info_read(multi.Get(),
|
||||
&msgs_in_queue)) != nullptr) {
|
||||
if (msg->msg == CURLMSG_DONE)
|
||||
input_curl_handle_done(msg->easy_handle, msg->data.result);
|
||||
@ -501,7 +497,7 @@ int
|
||||
CurlGlobal::TimerFunction(gcc_unused CURLM *_global, long timeout_ms, void *userp)
|
||||
{
|
||||
auto &global = *(CurlGlobal *)userp;
|
||||
assert(_global == global.multi);
|
||||
assert(_global == global.multi.Get());
|
||||
|
||||
if (timeout_ms < 0) {
|
||||
global.Cancel();
|
||||
@ -566,14 +562,14 @@ input_curl_init(const ConfigBlock &block)
|
||||
verify_peer = block.GetBlockValue("verify_peer", true);
|
||||
verify_host = block.GetBlockValue("verify_host", true);
|
||||
|
||||
CURLM *global = curl_multi_init();
|
||||
if (global == nullptr) {
|
||||
try {
|
||||
curl_global = new CurlGlobal(io_thread_get());
|
||||
} catch (const std::runtime_error &e) {
|
||||
LogError(e);
|
||||
curl_slist_free_all(http_200_aliases);
|
||||
curl_global_cleanup();
|
||||
throw PluginUnavailable("curl_multi_init() failed");
|
||||
}
|
||||
|
||||
curl_global = new CurlGlobal(io_thread_get(), global);
|
||||
}
|
||||
|
||||
static void
|
||||
|
91
src/lib/curl/Multi.hxx
Normal file
91
src/lib/curl/Multi.hxx
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Max Kellermann <max@duempel.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CURL_MULTI_HXX
|
||||
#define CURL_MULTI_HXX
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* An OO wrapper for a "CURLM*" (a libCURL "multi" handle).
|
||||
*/
|
||||
class CurlMulti {
|
||||
CURLM *handle = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Allocate a new CURLM*.
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*/
|
||||
CurlMulti()
|
||||
:handle(curl_multi_init())
|
||||
{
|
||||
if (handle == nullptr)
|
||||
throw std::runtime_error("curl_multi_init() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty instance.
|
||||
*/
|
||||
CurlMulti(std::nullptr_t):handle(nullptr) {}
|
||||
|
||||
CurlMulti(CurlMulti &&src):handle(std::exchange(src.handle, nullptr)) {}
|
||||
|
||||
~CurlMulti() {
|
||||
if (handle != nullptr)
|
||||
curl_multi_cleanup(handle);
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
CurlMulti &operator=(CurlMulti &&src) {
|
||||
std::swap(handle, src.handle);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CURL *Get() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SetOption(CURLMoption option, T value) {
|
||||
auto code = curl_multi_setopt(handle, option, value);
|
||||
if (code != CURLM_OK)
|
||||
throw std::runtime_error(curl_multi_strerror(code));
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user