reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit 361246ba698171a30bb4b3f471985f9d295193a9
parent 52e92ae034578572b7ada8030408ed4780a79522
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat, 28 Nov 2015 14:32:29 -0500

use libcurl instead of jnetlib to support ssl downloads

Diffstat:
MTupfile | 6+-----
Msrc/download.cpp | 115++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/download.hpp | 12+++++++-----
3 files changed, 72 insertions(+), 61 deletions(-)

diff --git a/Tupfile b/Tupfile @@ -6,7 +6,7 @@ CXXFLAGS += -O2 -std=c++14 CXXFLAGS += -Ivendor -Ivendor/WDL -Ivendor/WDL/WDL CXXFLAGS += -DWDL_NO_DEFINE_MINMAX -LDFLAGS := -framework Cocoa -framework Carbon +LDFLAGS := -framework Cocoa -framework Carbon -lcurl SOFLAGS := -dynamiclib WDL := vendor/WDL/WDL @@ -16,10 +16,6 @@ WDLSOURCE := $(SWELL)/swell.cpp $(SWELL)/swell-ini.cpp WDLSOURCE += $(SWELL)/swell-gdi.mm $(SWELL)/swell-kb.mm $(SWELL)/swell-menu.mm WDLSOURCE += $(SWELL)/swell-misc.mm $(SWELL)/swell-dlg.mm $(SWELL)/swell-wnd.mm -JNETLIB := $(WDL)/jnetlib -WDLSOURCE += $(JNETLIB)/util.cpp $(JNETLIB)/httpget.cpp -WDLSOURCE += $(JNETLIB)/connection.cpp $(JNETLIB)/asyncdns.cpp - TINYXML := $(WDL)/tinyxml WDLSOURCE += $(TINYXML)/tinyxml.cpp $(TINYXML)/tinystr.cpp WDLSOURCE += $(TINYXML)/tinyxmlparser.cpp $(TINYXML)/tinyxmlerror.cpp diff --git a/src/download.cpp b/src/download.cpp @@ -1,16 +1,17 @@ #include "download.hpp" -#include <WDL/jnetlib/httpget.h> -#include <WDL/jnetlib/jnetlib.h> +#include <curl/curl.h> #include <reaper_plugin_functions.h> -std::vector<Download *> Download::s_active; +using namespace std; -static const int DOWNLOAD_TIMEOUT = 10; +vector<Download *> Download::s_active; + +static const int DOWNLOAD_TIMEOUT = 5; Download::Download(const char *url) - : m_threadHandle(0), m_contents(0) + : m_threadHandle(0) { m_url = url; @@ -20,7 +21,7 @@ Download::Download(const char *url) Download::~Download() { if(!isFinished()) - s_active.erase(std::remove(s_active.begin(), s_active.end(), this)); + s_active.erase(remove(s_active.begin(), s_active.end(), this)); // call stop after removing from the active list to prevent // bad access from timeTick -> execCallbacks @@ -35,11 +36,7 @@ void Download::reset() m_aborted = false; m_finished = false; m_status = 0; - - if(m_contents) { - delete[] m_contents; - m_contents = 0; - } + m_contents.clear(); } void Download::addCallback(const DownloadCallback &callback) @@ -47,9 +44,9 @@ void Download::addCallback(const DownloadCallback &callback) m_callback.push_back(callback); } -void Download::timerTick() // static +void Download::TimerTick() { - std::vector<Download *> &activeDownloads = Download::s_active; + vector<Download *> &activeDownloads = Download::s_active; const int size = activeDownloads.size(); for(int i = 0; i < size; i++) { @@ -66,7 +63,7 @@ void Download::timerTick() // static } if(Download::s_active.empty()) - plugin_register("-timer", (void*)timerTick); + plugin_register("-timer", (void*)TimerTick); } Download::StartCode Download::start() @@ -77,9 +74,9 @@ Download::StartCode Download::start() reset(); s_active.push_back(this); - plugin_register("timer", (void*)timerTick); + plugin_register("timer", (void*)TimerTick); - m_threadHandle = CreateThread(NULL, 0, worker, (void *)this, 0, 0); + m_threadHandle = CreateThread(NULL, 0, Worker, (void *)this, 0, 0); return Started; } @@ -98,56 +95,72 @@ void Download::stop() // otherwise the callback will not be called }; -DWORD WINAPI Download::worker(void *ptr) // static +DWORD WINAPI Download::Worker(void *ptr) { - JNL::open_socketlib(); - Download *download = static_cast<Download *>(ptr); - JNL_HTTPGet agent; - agent.addheader("Accept: */*"); - agent.addheader("User-Agent: ReaPack (REAPER)"); - agent.connect(download->url()); - - const time_t startTime = time(NULL); - - while(agent.run() == 0) { - if(download->isAborted()) { - download->finish(-2, strdup("aborted")); - JNL::close_socketlib(); - return 1; - } - else if(time(NULL) - startTime >= DOWNLOAD_TIMEOUT) { - download->finish(-3, strdup("timeout")); - JNL::close_socketlib(); - return 1; - } - - Sleep(50); + string contents; + + CURL *curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_URL, download->url()); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "ReaPack/1.0 (REAPER)"); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, DOWNLOAD_TIMEOUT); + + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1); + + curl_easy_setopt(curl, CURLOPT_HEADER, true); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &contents); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData); + + const CURLcode res = curl_easy_perform(curl); + + if(download->isAborted()) { + download->finish(-2, "aborted"); + curl_easy_cleanup(curl); + return 1; + } + else if(res != CURLE_OK) { + download->finish(0, curl_easy_strerror(res)); + curl_easy_cleanup(curl); + return 1; } - const int status = agent.getreplycode(); - const int size = agent.bytes_available(); + int status = 0; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); if(status == 200) { - char *buffer = new char[size + 1]; - agent.get_bytes(buffer, size); + // strip headers + long headerSize = 0; + curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &headerSize); + contents.erase(0, headerSize); - // get_bytes doesn't put a null byte at the end of the string - // without the next line strlen(buffer) cound be anything - buffer[size] = '\0'; + download->finish(status, contents); + } + else { + // strip body + contents.erase(contents.find("\n")); - download->finish(status, buffer); + download->finish(status, contents); } - else - download->finish(status, strdup(agent.geterrorstr())); - JNL::close_socketlib(); + curl_easy_cleanup(curl); return 0; } -void Download::finish(const int status, const char *contents) +size_t Download::WriteData(char *ptr, size_t rawsize, size_t nmemb, void *data) +{ + const size_t size = rawsize * nmemb; + + string *str = static_cast<string *>(data); + str->append(ptr, size); + + return size; +} + + +void Download::finish(const int status, const string &contents) { WDL_MutexLock lock(&m_mutex); diff --git a/src/download.hpp b/src/download.hpp @@ -3,12 +3,13 @@ #include <functional> #include <vector> +#include <string> #include <WDL/mutex.h> #include <reaper_plugin.h> -typedef std::function<void(int, const char *)> DownloadCallback; +typedef std::function<void(int, const std::string &)> DownloadCallback; class Download { public: @@ -34,10 +35,11 @@ public: private: static std::vector<Download *> s_active; - static void timerTick(); - static DWORD WINAPI worker(void *ptr); + static void TimerTick(); + static size_t WriteData(char *, size_t, size_t, void *); + static DWORD WINAPI Worker(void *ptr); - void finish(const int status, const char *contents); + void finish(const int status, const std::string &contents); void execCallbacks(); void abort(); void reset(); @@ -46,7 +48,7 @@ private: bool m_aborted; bool m_finished; int m_status; - const char *m_contents; + std::string m_contents; const char *m_url; std::vector<DownloadCallback> m_callback;