diff --git a/include/downloader.h b/include/downloader.h new file mode 100644 index 000000000..347fb1f19 --- /dev/null +++ b/include/downloader.h @@ -0,0 +1,70 @@ +/* + * Copyright 2018 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef KIWIX_DOWNLOADER_H +#define KIWIX_DOWNLOADER_H + +#include +#include +#include + +namespace kiwix +{ + + +struct DownloadedFile { + DownloadedFile() + : success(false) {} + bool success; + std::string path; +}; + +/** + * A tool to download things. + * + */ +class Downloader +{ + public: + Downloader(); + ~Downloader(); + + /** + * Download a content. + * + * @param url the url to download + * @return the content downloaded. + */ + DownloadedFile download(const std::string& url); + + private: + static pthread_mutex_t globalLock; + + aria2::Session* session; + DownloadedFile* fileHandle; + std::string tmpDir; + + static int downloadEventCallback(aria2::Session* session, + aria2::DownloadEvent event, + aria2::A2Gid gid, + void* userData); +}; +} + +#endif diff --git a/include/meson.build b/include/meson.build index ac79e21ee..a3d6b1ea1 100644 --- a/include/meson.build +++ b/include/meson.build @@ -2,6 +2,7 @@ headers = [ 'library.h', 'manager.h', 'opds_dumper.h', + 'downloader.h', 'reader.h', 'searcher.h' ] diff --git a/meson.build b/meson.build index 43a76926d..6f875dc87 100644 --- a/meson.build +++ b/meson.build @@ -12,6 +12,7 @@ thread_dep = dependency('threads') libicu_dep = dependency('icu-i18n', static:static_deps) libzim_dep = dependency('libzim', version : '>=3.2.0', static:static_deps) pugixml_dep = dependency('pugixml', static:static_deps) +libaria2_dep = dependency('libaria2', static:static_deps) ctpp2_include_path = '' has_ctpp2_dep = false @@ -72,7 +73,7 @@ endif xapian_dep = dependency('xapian-core', required:false, static:static_deps) -all_deps = [thread_dep, libicu_dep, libzim_dep, xapian_dep, pugixml_dep] +all_deps = [thread_dep, libicu_dep, libzim_dep, xapian_dep, pugixml_dep, libaria2_dep] if has_ctpp2_dep all_deps += [ctpp2_dep] endif @@ -88,7 +89,7 @@ subdir('scripts') subdir('static') subdir('src') -pkg_requires = ['libzim', 'icu-i18n', 'pugixml'] +pkg_requires = ['libzim', 'icu-i18n', 'pugixml', 'libaria2'] if xapian_dep.found() pkg_requires += ['xapian-core'] endif diff --git a/src/downloader.cpp b/src/downloader.cpp new file mode 100644 index 000000000..b22429008 --- /dev/null +++ b/src/downloader.cpp @@ -0,0 +1,112 @@ +/* + * Copyright 2018 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "downloader.h" +#include "common/pathTools.h" + +#include +#include + +namespace kiwix +{ + +pthread_mutex_t Downloader::globalLock = PTHREAD_MUTEX_INITIALIZER; + + +/* Constructor */ +Downloader::Downloader() +{ + aria2::SessionConfig config; + config.downloadEventCallback = Downloader::downloadEventCallback; + config.userData = this; + tmpDir = makeTmpDirectory(); + aria2::KeyVals options; + options.push_back(std::pair("dir", tmpDir)); + session = aria2::sessionNew(options, config); +} + + +/* Destructor */ +Downloader::~Downloader() +{ + aria2::sessionFinal(session); + rmdir(tmpDir.c_str()); +} + + +int Downloader::downloadEventCallback(aria2::Session* session, + aria2::DownloadEvent event, + aria2::A2Gid gid, + void* userData) +{ + Downloader* downloader = static_cast(userData); + + auto fileHandle = downloader->fileHandle; + auto dh = aria2::getDownloadHandle(session, gid); + + if (!dh) { + return 0; + } + + switch (event) { + case aria2::EVENT_ON_DOWNLOAD_COMPLETE: + { + if (dh->getNumFiles() > 0) { + auto f = dh->getFile(1); + fileHandle->path = f.path; + fileHandle->success = true; + } + } + break; + case aria2::EVENT_ON_DOWNLOAD_ERROR: + { + fileHandle->success = false; + } + break; + default: + break; + } + aria2::deleteDownloadHandle(dh); + return 0; +} + +DownloadedFile Downloader::download(const std::string& url) { + pthread_mutex_lock(&globalLock); + DownloadedFile fileHandle; + try { + std::vector uris = {url}; + aria2::KeyVals options; + aria2::A2Gid gid; + int ret; + DownloadedFile fileHandle; + + ret = aria2::addUri(session, &gid, uris, options); + if (ret < 0) { + std::cerr << "Failed to download" << std::endl; + } else { + this->fileHandle = &fileHandle; + aria2::run(session, aria2::RUN_DEFAULT); + } + } catch (...) {}; + this->fileHandle = nullptr; + pthread_mutex_unlock(&globalLock); + return fileHandle; +} + +} diff --git a/src/meson.build b/src/meson.build index e977f2021..d3df0f4ad 100644 --- a/src/meson.build +++ b/src/meson.build @@ -2,6 +2,7 @@ kiwix_sources = [ 'library.cpp', 'manager.cpp', 'opds_dumper.cpp', + 'downloader.cpp', 'reader.cpp', 'searcher.cpp', 'common/base64.cpp',