浏览代码

Don't link with cURL and OpenSSL libraries.

Miku AuahDark 2 年之前
父节点
当前提交
d042495ec9
共有 3 个文件被更改,包括 90 次插入38 次删除
  1. 3 3
      src/CMakeLists.txt
  2. 77 28
      src/generic/CurlClient.cpp
  3. 10 7
      src/generic/CurlClient.h

+ 3 - 3
src/CMakeLists.txt

@@ -113,15 +113,15 @@ target_link_libraries (https https-common)
 if (USE_CURL_BACKEND)
 if (USE_CURL_BACKEND)
 	set(HTTPS_BACKEND_CURL ON)
 	set(HTTPS_BACKEND_CURL ON)
 	find_package (CURL REQUIRED)
 	find_package (CURL REQUIRED)
-	include_directories (${CURL_INCLUDE_DIR})
-	target_link_libraries (https https-curl ${CURL_LIBRARIES})
+	include_directories (${CURL_INCLUDE_DIRS})
+	target_link_libraries (https https-curl)
 endif ()
 endif ()
 
 
 if (USE_OPENSSL_BACKEND)
 if (USE_OPENSSL_BACKEND)
 	set(HTTPS_BACKEND_OPENSSL ON)
 	set(HTTPS_BACKEND_OPENSSL ON)
 	find_package (OpenSSL REQUIRED)
 	find_package (OpenSSL REQUIRED)
 	include_directories (${OPENSSL_INCLUDE_DIR})
 	include_directories (${OPENSSL_INCLUDE_DIR})
-	target_link_libraries (https https-openssl ${OPENSSL_LIBRARIES})
+	target_link_libraries (https https-openssl)
 endif ()
 endif ()
 
 
 if (USE_SCHANNEL_BACKEND)
 if (USE_SCHANNEL_BACKEND)

+ 77 - 28
src/generic/CurlClient.cpp

@@ -2,48 +2,91 @@
 
 
 #ifdef HTTPS_BACKEND_CURL
 #ifdef HTTPS_BACKEND_CURL
 
 
+#include <algorithm>
 #include <dlfcn.h>
 #include <dlfcn.h>
 #include <stdexcept>
 #include <stdexcept>
 #include <sstream>
 #include <sstream>
 #include <vector>
 #include <vector>
 
 
+typedef struct StringReader
+{
+	const std::string *str;
+	size_t pos;
+} StringReader;
+
+template<typename T> bool loadSymbol(void *handle, const char *name, T &out)
+{
+	out = (T) dlsym(handle, name);
+	return out != nullptr;
+}
+
 CurlClient::Curl::Curl()
 CurlClient::Curl::Curl()
+: loaded(false)
 {
 {
 	void *handle = dlopen("libcurl.so", RTLD_LAZY);
 	void *handle = dlopen("libcurl.so", RTLD_LAZY);
 	if (!handle)
 	if (!handle)
-	{
-		loaded = false;
 		return;
 		return;
-	}
 
 
-	void (*global_init)() = (void(*)()) dlsym(handle, "curl_global_init");
-	easy_init = (CURL*(*)()) dlsym(handle, "curl_easy_init");
-	easy_cleanup = (void(*)(CURL*)) dlsym(handle, "curl_easy_cleanup");
-	easy_setopt = (CURLcode(*)(CURL*,CURLoption,...)) dlsym(handle, "curl_easy_setopt");
-	easy_perform = (CURLcode(*)(CURL*)) dlsym(handle, "curl_easy_perform");
-	easy_getinfo = (CURLcode(*)(CURL*,CURLINFO,...)) dlsym(handle, "curl_easy_getinfo");
-	slist_append = (curl_slist*(*)(curl_slist*,const char*)) dlsym(handle, "curl_slist_append");
-	slist_free_all = (void(*)(curl_slist*)) dlsym(handle, "curl_slist_free_all");
+	// Load symbols
+	void(*global_init)(long) = nullptr;
+	if (!loadSymbol(handle, "curl_global_init", global_init))
+		return;
+	if (!loadSymbol(handle, "curl_global_cleanup", global_cleanup))
+		return;
+	if (!loadSymbol(handle, "curl_easy_init", easy_init))
+		return;
+	if (!loadSymbol(handle, "curl_easy_cleanup", easy_cleanup))
+		return;
+	if (!loadSymbol(handle, "curl_easy_setopt", easy_setopt))
+		return;
+	if (!loadSymbol(handle, "curl_easy_perform", easy_perform))
+		return;
+	if (!loadSymbol(handle, "curl_easy_getinfo", easy_getinfo))
+		return;
+	if (!loadSymbol(handle, "curl_slist_append", slist_append))
+		return;
+	if (!loadSymbol(handle, "curl_slist_free_all", slist_free_all))
+		return;
 
 
-	loaded = (global_init && easy_init && easy_cleanup && easy_setopt && easy_perform && easy_getinfo && slist_append && slist_free_all);
+	global_init(CURL_GLOBAL_DEFAULT);
+	loaded = true;
+}
 
 
-	if (!loaded)
-		return;
+CurlClient::Curl::~Curl()
+{
+	if (loaded)
+		global_cleanup();
+}
 
 
-	global_init();
+static char toUppercase(char c)
+{
+	int ch = (unsigned char) c;
+	return toupper(ch);
 }
 }
 
 
-static size_t stringstreamWriter(char *ptr, size_t size, size_t nmemb, void *userdata)
+static size_t stringReader(char *ptr, size_t size, size_t nmemb, StringReader *reader)
+{
+	const char *data = reader->str->data();
+	size_t len = reader->str->length();
+	size_t maxCount = (len - reader->pos) / size;
+	size_t desiredBytes = std::min(maxCount, nmemb) * size;
+
+	std::copy(data + reader->pos, data + desiredBytes, ptr);
+	reader->pos += desiredBytes;
+
+	return desiredBytes;
+}
+
+static size_t stringstreamWriter(char *ptr, size_t size, size_t nmemb, std::stringstream *ss)
 {
 {
-	std::stringstream *ss = (std::stringstream*) userdata;
 	size_t count = size*nmemb;
 	size_t count = size*nmemb;
 	ss->write(ptr, count);
 	ss->write(ptr, count);
 	return count;
 	return count;
 }
 }
 
 
-static size_t headerWriter(char *ptr, size_t size, size_t nmemb, void *userdata)
+static size_t headerWriter(char *ptr, size_t size, size_t nmemb, std::map<std::string,std::string> *userdata)
 {
 {
-	std::map<std::string, std::string> &headers = *((std::map<std::string,std::string>*) userdata);
+	std::map<std::string, std::string> &headers = *userdata;
 	size_t count = size*nmemb;
 	size_t count = size*nmemb;
 	std::string line(ptr, count);
 	std::string line(ptr, count);
 	size_t split = line.find(':');
 	size_t split = line.find(':');
@@ -64,7 +107,7 @@ bool CurlClient::valid() const
 HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
 HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
 {
 {
 	Reply reply;
 	Reply reply;
-	reply.responseCode = 400;
+	reply.responseCode = 0;
 
 
 	CURL *handle = curl.easy_init();
 	CURL *handle = curl.easy_init();
 	if (!handle)
 	if (!handle)
@@ -73,17 +116,23 @@ HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
 	curl.easy_setopt(handle, CURLOPT_URL, req.url.c_str());
 	curl.easy_setopt(handle, CURLOPT_URL, req.url.c_str());
 	curl.easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
 	curl.easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
 
 
-	if (req.method == "PUT")
-		curl.easy_setopt(handle, CURLOPT_PUT, 1L);
-	else if (req.method == "POST")
-		curl.easy_setopt(handle, CURLOPT_POST, 1L);
+	std::string method = req.method;
+	if (method == "")
+		method = "GET";
 	else
 	else
-		curl.easy_setopt(handle, CURLOPT_CUSTOMREQUEST, req.method.c_str());
+		std::transform(method.begin(), method.end(), method.begin(), toUppercase);
+	curl.easy_setopt(handle, CURLOPT_CUSTOMREQUEST, method.c_str());
+
+	StringReader reader;
 
 
-	if (req.postdata.size() > 0 && (req.method != "GET" && req.method != "HEAD"))
+	if (req.postdata.size() > 0 && (method != "GET" && method != "HEAD"))
 	{
 	{
-		curl.easy_setopt(handle, CURLOPT_POSTFIELDS, req.postdata.c_str());
-		curl.easy_setopt(handle, CURLOPT_POSTFIELDSIZE, req.postdata.size());
+		reader.str = &req.postdata;
+		reader.pos = 0;
+		curl.easy_setopt(handle, CURLOPT_UPLOAD, 1L);
+		curl.easy_setopt(handle, CURLOPT_READFUNCTION, stringReader);
+		curl.easy_setopt(handle, CURLOPT_READDATA, &reader);
+		curl.easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) req.postdata.length());
 	}
 	}
 
 
 	// Curl doesn't copy memory, keep the strings around
 	// Curl doesn't copy memory, keep the strings around

+ 10 - 7
src/generic/CurlClient.h

@@ -18,16 +18,19 @@ private:
 	static struct Curl
 	static struct Curl
 	{
 	{
 		Curl();
 		Curl();
+		~Curl();
 		bool loaded;
 		bool loaded;
 
 
-		CURL *(*easy_init)();
-		void (*easy_cleanup)(CURL *handle);
-		CURLcode (*easy_setopt)(CURL *handle, CURLoption option, ...);
-		CURLcode (*easy_perform)(CURL *easy_handle);
-		CURLcode (*easy_getinfo)(CURL *curl, CURLINFO info, ...);
+		decltype(&curl_global_cleanup) global_cleanup;
 
 
-		curl_slist *(*slist_append)(curl_slist *list, const char *string);
-		void (*slist_free_all)(curl_slist *list);
+		decltype(&curl_easy_init) easy_init;
+		decltype(&curl_easy_cleanup) easy_cleanup;
+		decltype(&curl_easy_setopt) easy_setopt;
+		decltype(&curl_easy_perform) easy_perform;
+		decltype(&curl_easy_getinfo) easy_getinfo;
+
+		decltype(&curl_slist_append) slist_append;
+		decltype(&curl_slist_free_all) slist_free_all;
 	} curl;
 	} curl;
 };
 };