Mercurial > minori
annotate src/core/http.cc @ 291:9a88e1725fd2
*: refactor lots of stuff
I forgot to put this into different commits, oops!
anyway, it doesn't really matter *that* much since this is an
unfinished hobby project anyway. once it starts getting stable
commit history will be more important, but for now it's not
that big of a deal
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Sun, 12 May 2024 16:31:07 -0400 |
| parents | 862d0d8619f6 |
| children | b1f625b0227c |
| rev | line source |
|---|---|
| 75 | 1 #include "core/http.h" |
| 2 #include "core/session.h" | |
| 3 #include <QByteArray> | |
| 4 #include <curl/curl.h> | |
| 258 | 5 #include <iostream> |
| 75 | 6 #include <string> |
| 7 #include <vector> | |
| 8 | |
| 9 namespace HTTP { | |
| 10 | |
| 77 | 11 static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) { |
| 75 | 12 reinterpret_cast<QByteArray*>(userdata)->append(reinterpret_cast<char*>(contents), size * nmemb); |
| 13 return size * nmemb; | |
| 14 } | |
| 15 | |
| 291 | 16 QByteArray Request(const std::string& url, const std::vector<std::string>& headers, const std::string& data, Type type) { |
| 75 | 17 struct curl_slist* list = NULL; |
| 18 QByteArray userdata; | |
| 19 | |
| 20 CURL* curl = curl_easy_init(); | |
| 21 if (curl) { | |
| 291 | 22 for (const std::string& h : headers) |
| 75 | 23 list = curl_slist_append(list, h.c_str()); |
| 291 | 24 |
| 77 | 25 curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); |
| 291 | 26 if (type == Type::Post) |
| 27 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); | |
| 77 | 28 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); |
| 75 | 29 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata); |
| 30 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); | |
| 31 /* Use system certs... useful on Windows. */ | |
| 32 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); | |
|
221
53211cb1e7f5
library: add initial library stuff
Paper <paper@paper.us.eu.org>
parents:
175
diff
changeset
|
33 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // threading |
| 75 | 34 CURLcode res = curl_easy_perform(curl); |
| 35 session.IncrementRequests(); | |
| 36 curl_easy_cleanup(curl); | |
| 175 | 37 if (res != CURLE_OK) |
| 38 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl; | |
| 75 | 39 } |
| 77 | 40 return userdata; |
| 75 | 41 } |
| 42 | |
| 291 | 43 /* this function is static */ |
| 44 size_t RequestThread::WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) { | |
| 45 RequestThread* thread = reinterpret_cast<RequestThread*>(userdata); | |
| 46 | |
| 47 const std::lock_guard<std::mutex> lock(thread->callback_data_mutex_); | |
| 48 | |
| 49 /* stop writing, then! */ | |
| 50 if (thread->cancelled_) | |
| 51 return CURL_WRITEFUNC_ERROR; | |
| 52 | |
| 53 /* else, continue on as normal */ | |
| 54 thread->array_.append(reinterpret_cast<char*>(contents), size * nmemb); | |
| 55 return size * nmemb; | |
| 56 } | |
| 57 | |
| 58 RequestThread::RequestThread(Type type, QObject* parent) : QThread(parent) { | |
| 59 SetType(type); | |
| 60 } | |
| 61 | |
| 62 RequestThread::RequestThread(const std::string& url, const std::vector<std::string>& headers, | |
| 63 const std::string& data, Type type, QObject* parent) | |
| 64 : QThread(parent) { | |
| 65 SetUrl(url); | |
| 66 SetData(data); | |
| 67 SetHeaders(headers); | |
| 68 SetType(type); | |
| 69 } | |
| 70 | |
| 71 RequestThread::~RequestThread() { | |
| 72 /* block until the function can safely exit. | |
| 73 * | |
| 74 * this sucks. find out a better way to do this, which will probably | |
| 75 * be to put all of the threads in a pool */ | |
| 76 Stop(); | |
| 77 wait(); | |
| 78 } | |
| 79 | |
| 80 void RequestThread::SetUrl(const std::string& url) { | |
| 81 url_ = url; | |
| 82 } | |
| 83 | |
| 84 void RequestThread::SetHeaders(const std::vector<std::string>& headers) { | |
| 85 headers_ = headers; | |
| 86 } | |
| 87 | |
| 88 void RequestThread::SetData(const std::string& data) { | |
| 89 data_ = data; | |
| 90 } | |
| 91 | |
| 92 void RequestThread::SetType(Type type) { | |
| 93 type_ = type; | |
| 94 } | |
| 95 | |
| 96 void RequestThread::run() { | |
| 77 | 97 struct curl_slist* list = NULL; |
| 75 | 98 |
| 99 CURL* curl = curl_easy_init(); | |
| 100 if (curl) { | |
| 291 | 101 curl_easy_setopt(curl, CURLOPT_URL, url_.c_str()); |
| 102 | |
| 103 if (type_ == Type::Post) | |
| 104 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_.c_str()); | |
| 105 | |
| 106 for (const std::string& h : headers_) | |
| 75 | 107 list = curl_slist_append(list, h.c_str()); |
| 108 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); | |
| 291 | 109 |
| 110 curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); | |
| 111 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestThread::WriteCallback); | |
| 112 | |
| 75 | 113 /* Use system certs... useful on Windows. */ |
| 114 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); | |
| 291 | 115 |
| 116 /* does something with threading, don't remember what though */ | |
| 117 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); | |
| 118 | |
| 75 | 119 CURLcode res = curl_easy_perform(curl); |
| 120 session.IncrementRequests(); | |
| 121 curl_easy_cleanup(curl); | |
| 291 | 122 |
| 123 callback_data_mutex_.lock(); | |
| 124 if (res != CURLE_OK && !(res == CURLE_WRITE_ERROR && cancelled_)) | |
| 175 | 125 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl; |
| 291 | 126 callback_data_mutex_.unlock(); |
| 75 | 127 } |
| 291 | 128 |
| 129 emit ReceivedData(array_); | |
| 130 array_.clear(); | |
| 131 } | |
| 132 | |
| 133 void RequestThread::Stop() { | |
| 134 const std::lock_guard<std::mutex> lock(callback_data_mutex_); | |
| 135 cancelled_ = true; | |
| 75 | 136 } |
| 137 | |
| 76 | 138 } // namespace HTTP |
