comparison 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
comparison
equal deleted inserted replaced
290:9347e2eaf6e5 291:9a88e1725fd2
11 static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) { 11 static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) {
12 reinterpret_cast<QByteArray*>(userdata)->append(reinterpret_cast<char*>(contents), size * nmemb); 12 reinterpret_cast<QByteArray*>(userdata)->append(reinterpret_cast<char*>(contents), size * nmemb);
13 return size * nmemb; 13 return size * nmemb;
14 } 14 }
15 15
16 QByteArray Get(const std::string& url, const std::vector<std::string>& headers) { 16 QByteArray Request(const std::string& url, const std::vector<std::string>& headers, const std::string& data, Type type) {
17 struct curl_slist* list = NULL; 17 struct curl_slist* list = NULL;
18 QByteArray userdata; 18 QByteArray userdata;
19 19
20 CURL* curl = curl_easy_init(); 20 CURL* curl = curl_easy_init();
21 if (curl) { 21 if (curl) {
22 for (const std::string& h : headers) { 22 for (const std::string& h : headers)
23 list = curl_slist_append(list, h.c_str()); 23 list = curl_slist_append(list, h.c_str());
24 } 24
25 curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 25 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
26 if (type == Type::Post)
27 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
26 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); 28 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
27 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata); 29 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata);
28 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); 30 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
29 /* Use system certs... useful on Windows. */ 31 /* Use system certs... useful on Windows. */
30 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); 32 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
36 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl; 38 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl;
37 } 39 }
38 return userdata; 40 return userdata;
39 } 41 }
40 42
41 QByteArray Post(const std::string& url, const std::string& data, const std::vector<std::string>& headers) { 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() {
42 struct curl_slist* list = NULL; 97 struct curl_slist* list = NULL;
43 QByteArray userdata;
44 98
45 CURL* curl = curl_easy_init(); 99 CURL* curl = curl_easy_init();
46 if (curl) { 100 if (curl) {
47 for (const std::string& h : headers) { 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_)
48 list = curl_slist_append(list, h.c_str()); 107 list = curl_slist_append(list, h.c_str());
49 }
50 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
51 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
52 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); 108 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
53 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata); 109
54 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); 110 curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
111 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestThread::WriteCallback);
112
55 /* Use system certs... useful on Windows. */ 113 /* Use system certs... useful on Windows. */
56 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); 114 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
57 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // threading 115
116 /* does something with threading, don't remember what though */
117 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
118
58 CURLcode res = curl_easy_perform(curl); 119 CURLcode res = curl_easy_perform(curl);
59 session.IncrementRequests(); 120 session.IncrementRequests();
60 curl_easy_cleanup(curl); 121 curl_easy_cleanup(curl);
61 if (res != CURLE_OK) 122
123 callback_data_mutex_.lock();
124 if (res != CURLE_OK && !(res == CURLE_WRITE_ERROR && cancelled_))
62 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl; 125 std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl;
126 callback_data_mutex_.unlock();
63 } 127 }
64 return userdata; 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;
65 } 136 }
66 137
67 } // namespace HTTP 138 } // namespace HTTP