diff 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
line wrap: on
line diff
--- a/src/core/http.cc	Wed May 08 17:32:28 2024 -0400
+++ b/src/core/http.cc	Sun May 12 16:31:07 2024 -0400
@@ -13,16 +13,18 @@
 	return size * nmemb;
 }
 
-QByteArray Get(const std::string& url, const std::vector<std::string>& headers) {
+QByteArray Request(const std::string& url, const std::vector<std::string>& headers, const std::string& data, Type type) {
 	struct curl_slist* list = NULL;
 	QByteArray userdata;
 
 	CURL* curl = curl_easy_init();
 	if (curl) {
-		for (const std::string& h : headers) {
+		for (const std::string& h : headers)
 			list = curl_slist_append(list, h.c_str());
-		}
+
 		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+		if (type == Type::Post)
+			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
 		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
 		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata);
 		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
@@ -38,30 +40,99 @@
 	return userdata;
 }
 
-QByteArray Post(const std::string& url, const std::string& data, const std::vector<std::string>& headers) {
+/* this function is static */
+size_t RequestThread::WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) {
+	RequestThread* thread = reinterpret_cast<RequestThread*>(userdata);
+
+	const std::lock_guard<std::mutex> lock(thread->callback_data_mutex_);
+
+	/* stop writing, then! */
+	if (thread->cancelled_)
+		return CURL_WRITEFUNC_ERROR;
+
+	/* else, continue on as normal */
+	thread->array_.append(reinterpret_cast<char*>(contents), size * nmemb);
+	return size * nmemb;
+}
+
+RequestThread::RequestThread(Type type, QObject* parent) : QThread(parent) {
+	SetType(type);
+}
+
+RequestThread::RequestThread(const std::string& url, const std::vector<std::string>& headers,
+	                         const std::string& data, Type type, QObject* parent)
+	: QThread(parent) {
+	SetUrl(url);
+	SetData(data);
+	SetHeaders(headers);
+	SetType(type);
+}
+
+RequestThread::~RequestThread() {
+	/* block until the function can safely exit.
+	 *
+	 * this sucks. find out a better way to do this, which will probably
+	 * be to put all of the threads in a pool */
+	Stop();
+	wait();
+}
+
+void RequestThread::SetUrl(const std::string& url) {
+	url_ = url;
+}
+
+void RequestThread::SetHeaders(const std::vector<std::string>& headers) {
+	headers_ = headers;
+}
+
+void RequestThread::SetData(const std::string& data) {
+	data_ = data;
+}
+
+void RequestThread::SetType(Type type) {
+	type_ = type;
+}
+
+void RequestThread::run() {
 	struct curl_slist* list = NULL;
-	QByteArray userdata;
 
 	CURL* curl = curl_easy_init();
 	if (curl) {
-		for (const std::string& h : headers) {
+		curl_easy_setopt(curl, CURLOPT_URL, url_.c_str());
+
+		if (type_ == Type::Post)
+			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_.c_str());
+
+		for (const std::string& h : headers_)
 			list = curl_slist_append(list, h.c_str());
-		}
-		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
 		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata);
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
+
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestThread::WriteCallback);
+
 		/* Use system certs... useful on Windows. */
 		curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
-		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // threading
+
+		/* does something with threading, don't remember what though */
+		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+
 		CURLcode res = curl_easy_perform(curl);
 		session.IncrementRequests();
 		curl_easy_cleanup(curl);
-		if (res != CURLE_OK)
+
+		callback_data_mutex_.lock();
+		if (res != CURLE_OK && !(res == CURLE_WRITE_ERROR && cancelled_))
 			std::cerr << "curl_easy_perform(curl) failed!: " << curl_easy_strerror(res) << std::endl;
+		callback_data_mutex_.unlock();
 	}
-	return userdata;
+
+	emit ReceivedData(array_);
+	array_.clear();
+}
+
+void RequestThread::Stop() {
+	const std::lock_guard<std::mutex> lock(callback_data_mutex_);
+	cancelled_ = true;
 }
 
 } // namespace HTTP