diff --git a/harbour-seaprint.pro b/harbour-seaprint.pro index 261c5a9..426ecb0 100644 --- a/harbour-seaprint.pro +++ b/harbour-seaprint.pro @@ -36,7 +36,6 @@ DEFINES += SEAPRINT_VERSION='\\"$$VERSION\\"' SOURCES += src/harbour-seaprint.cpp \ src/convertchecker.cpp \ src/curlrequester.cpp \ - src/curlworker.cpp \ src/ippdiscovery.cpp \ src/ippmsg.cpp \ src/ippprinter.cpp \ @@ -83,7 +82,6 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \ HEADERS += \ src/convertchecker.h \ src/curlrequester.h \ - src/curlworker.h \ src/ippdiscovery.h \ src/ippmsg.h \ src/ippprinter.h \ diff --git a/src/curlrequester.cpp b/src/curlrequester.cpp index 38af70f..ad3f426 100644 --- a/src/curlrequester.cpp +++ b/src/curlrequester.cpp @@ -1,28 +1,86 @@ #include "curlrequester.h" #include +#include "settings.h" -CurlRequester::CurlRequester(QUrl addr) : _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0), _performer(addr, this) +static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp) { - _performer.start(); + CurlRequester* cid = (CurlRequester*)userp; + return cid->requestWrite(dest, size*nmemb); +} + +CurlRequester::CurlRequester(QUrl addr, Role role) + : _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0), _curl(curl_easy_init()) +{ + + curl_easy_setopt(_curl, CURLOPT_URL, addr.toString().toStdString().c_str()); + + curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1L); + if(Settings::instance()->ignoreSslErrors()) + { + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYSTATUS, 0L); + } + + _opts = NULL; + _opts = curl_slist_append(_opts, "User-Agent: SeaPrint " SEAPRINT_VERSION); + + + switch (role) { + case IppRequest: + { + curl_easy_setopt(_curl, CURLOPT_POST, 1L); + curl_easy_setopt(_curl, CURLOPT_READFUNCTION, trampoline); + curl_easy_setopt(_curl, CURLOPT_READDATA, this); + + _opts = curl_slist_append(_opts, "Expect:"); + _opts = curl_slist_append(_opts, "Transfer-Encoding: chunked"); + _opts = curl_slist_append(_opts, "Content-Type: application/ipp"); + _opts = curl_slist_append(_opts, "Accept-Encoding: identity"); + break; + } + case HttpGetRequest: + { + curl_easy_setopt(_curl, CURLOPT_HTTPGET, 1L); + break; + } + } + + curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _opts); + + _worker = QtConcurrent::run([this](){ + Bytestream buf; + curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &buf); + curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, write_callback); + + CURLcode res = curl_easy_perform(_curl); + if(res != CURLE_OK) + qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res); + + emit done(res, buf); + }); } CurlRequester::~CurlRequester() { while(!_canWrite.tryAcquire(1, 500)) { - if(!_performer.isRunning()) + if(!_worker.isRunning()) { break; } } _done = true; _canRead.release(); - _performer.wait(); + _worker.waitForFinished(); if(_dest != nullptr) { delete _dest; } + + curl_slist_free_all(_opts); + curl_easy_cleanup(_curl); } bool CurlRequester::write(const char *data, size_t size) @@ -30,7 +88,7 @@ bool CurlRequester::write(const char *data, size_t size) qDebug() << "write " << size; while(!_canWrite.tryAcquire(1, 500)) { - if(!_performer.isRunning()) + if(!_worker.isRunning()) { return false; } diff --git a/src/curlrequester.h b/src/curlrequester.h index e13d19f..b54b98c 100644 --- a/src/curlrequester.h +++ b/src/curlrequester.h @@ -5,29 +5,56 @@ #include #include #include +#include #include +#include #include -#include "curlworker.h" +#include class CurlRequester : public QObject { Q_OBJECT public: - CurlRequester(QUrl addr); - ~CurlRequester(); + enum Role { + IppRequest, + HttpGetRequest + }; - template - bool setFinishedCallback(const Class* receiverObject, Callback cb) - { - connect(&_performer, &CurlWorker::done, receiverObject, cb); - return true; - } + CurlRequester(QUrl addr, Role role = IppRequest); + ~CurlRequester(); bool write(const char *data, size_t size); size_t requestWrite(char* dest, size_t size); + static size_t write_callback(char *ptr, size_t size, size_t nmemb, void* userdata) + { + size_t bytes_to_write = size*nmemb; + ((Bytestream*)userdata)->putBytes(ptr, bytes_to_write); + return bytes_to_write; + } + +signals: + void done(CURLcode, Bytestream); private: + CurlRequester(); + + // Container for the cURL global init and cleanup + class GlobalEnv + { + public: + GlobalEnv() + { + curl_global_init(CURL_GLOBAL_DEFAULT); + } + ~GlobalEnv() + { + curl_global_cleanup(); + } + }; + // Must be run exactly once, thus static + static GlobalEnv _gEnv; + QUrl _addr; QSemaphore _canWrite; @@ -39,7 +66,12 @@ private: size_t _size; size_t _offset; - CurlWorker _performer; + friend class CurlWorker; + + CURL* _curl; + struct curl_slist* _opts = NULL; + + QFuture _worker; }; #endif // CURLREQUESTER_H diff --git a/src/curlworker.cpp b/src/curlworker.cpp deleted file mode 100644 index b887568..0000000 --- a/src/curlworker.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "curlworker.h" -#include "curlrequester.h" -#include "settings.h" - -static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp) -{ - CurlRequester* cid = (CurlRequester*)userp; - return cid->requestWrite(dest, size*nmemb); -} - -CurlWorker::CurlWorker(QUrl addr, void* parent) -{ - _curl = curl_easy_init(); -// if(!curl) -// return false; - - curl_easy_setopt(_curl, CURLOPT_URL, addr.toString().toStdString().c_str()); - curl_easy_setopt(_curl, CURLOPT_POST, 1L); - curl_easy_setopt(_curl, CURLOPT_READFUNCTION, trampoline); - curl_easy_setopt(_curl, CURLOPT_READDATA, parent); -// curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1L); - if(Settings::instance()->ignoreSslErrors()) - { - curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYSTATUS, 0L); - } - - _opts = NULL; - - _opts = curl_slist_append(_opts, "Expect:"); - _opts = curl_slist_append(_opts, "Transfer-Encoding: chunked"); - _opts = curl_slist_append(_opts, "Content-Type: application/ipp"); - _opts = curl_slist_append(_opts, "User-Agent: SeaPrint " SEAPRINT_VERSION); - _opts = curl_slist_append(_opts, "Accept-Encoding: identity"); - - curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _opts); - -} - -CurlWorker::~CurlWorker() -{ - curl_slist_free_all(_opts); - curl_easy_cleanup(_curl); -} - -void CurlWorker::run(){ - Bytestream buf; - curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &buf); - curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, write_callback); - - CURLcode res = curl_easy_perform(_curl); - if(res != CURLE_OK) - qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res); - - emit done(res, buf); -} diff --git a/src/curlworker.h b/src/curlworker.h deleted file mode 100644 index d5985d0..0000000 --- a/src/curlworker.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef CURLWORKER_H -#define CURLWORKER_H - -#include -#include -#include -#include -#include - -class CurlWorker : public QThread -{ - Q_OBJECT -public: - CurlWorker(QUrl addr, void* parent); - ~CurlWorker(); - - void run() override; - - static size_t write_callback(char *ptr, size_t size, size_t nmemb, void* userdata) - { - size_t bytes_to_write = size*nmemb; - ((Bytestream*)userdata)->putBytes(ptr, bytes_to_write); - return bytes_to_write; - } -signals: - void done(CURLcode, Bytestream); - -private: - // Container for the cURL global init and cleanup - class GlobalEnv - { - public: - GlobalEnv() - { - curl_global_init(CURL_GLOBAL_DEFAULT); - } - ~GlobalEnv() - { - curl_global_cleanup(); - } - }; - // Must be run exactly once, thus static - static GlobalEnv _gEnv; - - CurlWorker(); - CURL* _curl = nullptr; - struct curl_slist* _opts; -}; - - -#endif // CURLWORKER_H