Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WinINet+Boost::url Instead of cURL for Windows #2613

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,6 @@ jobs:
mingw-w64-ucrt-x86_64-boost
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-cppwinrt
mingw-w64-ucrt-x86_64-curl
mingw-w64-ucrt-x86_64-graphviz
mingw-w64-ucrt-x86_64-miniupnpc
mingw-w64-ucrt-x86_64-nlohmann-json
Expand Down
1 change: 0 additions & 1 deletion cmake/compile_definitions/common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,4 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
${FFMPEG_LIBRARIES}
${Boost_LIBRARIES}
${OPENSSL_LIBRARIES}
${CURL_LIBRARIES}
${PLATFORM_LIBRARIES})
6 changes: 5 additions & 1 deletion cmake/compile_definitions/unix.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# unix specific compile definitions
# put anything here that applies to both linux and macos

list(APPEND SUNSHINE_EXTERNAL_LIBRARIES Boost::log)
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
Boost::log
${CURL_LIBRARIES})
set(PLATFORM_TARGET_FILES
"${CMAKE_SOURCE_DIR}/src/httpcommon_curl.cpp")

# add install prefix to assets path if not already there
if(NOT SUNSHINE_ASSETS_DIR MATCHES "^${CMAKE_INSTALL_PREFIX}")
Expand Down
11 changes: 4 additions & 7 deletions cmake/compile_definitions/windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-misleading-indentation)
# see gcc bug 98723
add_definitions(-DUSE_BOOST_REGEX)

# curl
add_definitions(-DCURL_STATICLIB)
include_directories(SYSTEM ${CURL_STATIC_INCLUDE_DIRS})
link_directories(${CURL_STATIC_LIBRARY_DIRS})

# miniupnpc
add_definitions(-DMINIUPNP_STATICLIB)

Expand Down Expand Up @@ -78,10 +73,12 @@ list(PREPEND PLATFORM_LIBRARIES
avrt
iphlpapi
shlwapi
PkgConfig::NLOHMANN_JSON
${CURL_STATIC_LIBRARIES})
wininet
Boost::url
PkgConfig::NLOHMANN_JSON)

if(SUNSHINE_ENABLE_TRAY)
list(APPEND PLATFORM_TARGET_FILES
"${CMAKE_SOURCE_DIR}/src/httpcommon_win.cpp"
"${CMAKE_SOURCE_DIR}/third-party/tray/src/tray_windows.c")
endif()
2 changes: 1 addition & 1 deletion cmake/dependencies/windows.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# windows specific dependencies

set(Boost_USE_STATIC_LIBS ON) # cmake-lint: disable=C0103
find_package(Boost 1.71.0 COMPONENTS locale log filesystem program_options REQUIRED)
find_package(Boost 1.71.0 COMPONENTS locale log filesystem program_options url REQUIRED)

# nlohmann_json
pkg_check_modules(NLOHMANN_JSON nlohmann_json REQUIRED IMPORTED_TARGET)
54 changes: 0 additions & 54 deletions src/httpcommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <Simple-Web-Server/server_http.hpp>
#include <Simple-Web-Server/server_https.hpp>
#include <boost/asio/ssl/context_base.hpp>
#include <curl/curl.h>

#include "config.h"
#include "crypto.h"
Expand Down Expand Up @@ -193,57 +192,4 @@ namespace http {
return 0;
}

bool
download_file(const std::string &url, const std::string &file) {
CURL *curl = curl_easy_init();
if (!curl) {
BOOST_LOG(error) << "Couldn't create CURL instance";
return false;
}
FILE *fp = fopen(file.c_str(), "wb");
if (!fp) {
BOOST_LOG(error) << "Couldn't open ["sv << file << ']';
curl_easy_cleanup(curl);
return false;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
#ifdef _WIN32
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
#endif
CURLcode result = curl_easy_perform(curl);
if (result != CURLE_OK) {
BOOST_LOG(error) << "Couldn't download ["sv << url << ", code:" << result << ']';
}
curl_easy_cleanup(curl);
fclose(fp);
return result == CURLE_OK;
}

std::string
url_escape(const std::string &url) {
CURL *curl = curl_easy_init();
char *string = curl_easy_escape(curl, url.c_str(), url.length());
std::string result(string);
curl_free(string);
curl_easy_cleanup(curl);
return result;
}

std::string
url_get_host(const std::string &url) {
CURLU *curlu = curl_url();
curl_url_set(curlu, CURLUPART_URL, url.c_str(), url.length());
char *host;
if (curl_url_get(curlu, CURLUPART_HOST, &host, 0) != CURLUE_OK) {
curl_url_cleanup(curlu);
return "";
}
std::string result(host);
curl_free(host);
curl_url_cleanup(curlu);
return result;
}

} // namespace http
7 changes: 6 additions & 1 deletion src/httpcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ namespace http {
reload_user_creds(const std::string &file);
bool
download_file(const std::string &url, const std::string &file);
/**
* Percent-encodes a string into a URL-safe format.
* @param str
* @return
*/
std::string
url_escape(const std::string &url);
url_escape(const std::string &str);
std::string
url_get_host(const std::string &url);

Expand Down
58 changes: 58 additions & 0 deletions src/httpcommon_curl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <curl/curl.h>
#include <string>

#include "logging.h"

namespace http {
using namespace std::literals;

bool
download_file(const std::string &url, const std::string &file) {
CURL *curl = curl_easy_init();
if (!curl) {
BOOST_LOG(error) << "Couldn't create CURL instance";
return false;
}
FILE *fp = fopen(file.c_str(), "wb");
if (!fp) {
BOOST_LOG(error) << "Couldn't open ["sv << file << ']';
curl_easy_cleanup(curl);
return false;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
CURLcode result = curl_easy_perform(curl);
if (result != CURLE_OK) {
BOOST_LOG(error) << "Couldn't download ["sv << url << ", code:" << result << ']';
}
curl_easy_cleanup(curl);
fclose(fp);
return result == CURLE_OK;
}

std::string
url_escape(const std::string &url) {
CURL *curl = curl_easy_init();
char *string = curl_easy_escape(curl, url.c_str(), (int) url.length());
std::string result(string);
curl_free(string);
curl_easy_cleanup(curl);
return result;
}

std::string
url_get_host(const std::string &url) {
CURLU *curlu = curl_url();
curl_url_set(curlu, CURLUPART_URL, url.c_str(), url.length());
char *host;
if (curl_url_get(curlu, CURLUPART_HOST, &host, 0) != CURLUE_OK) {
curl_url_cleanup(curlu);
return "";
}
std::string result(host);
curl_free(host);
curl_url_cleanup(curlu);
return result;
}
} // namespace http
65 changes: 65 additions & 0 deletions src/httpcommon_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <fstream>
#include <string>

#include <boost/url.hpp>
#include <windows.h>
#include <wininet.h>

namespace http {

using namespace boost::urls;

bool
download_file(const std::string &url, const std::string &file) {
HINTERNET hInternet, hConnect;
DWORD bytesRead;

// Initialize WinINet
hInternet = InternetOpenA("Sunshine", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
if (hInternet == nullptr) {
// Handle error
return false;
}

// Connect to the website
hConnect = InternetOpenUrlA(hInternet, url.c_str(), nullptr, 0, INTERNET_FLAG_RELOAD, 0);
if (hConnect == nullptr) {
// Handle error
InternetCloseHandle(hInternet);
return false;
}

// Create a buffer to receive the data
char buffer[4096];

// Open the destination file
std::ofstream outFile(file, std::ios::binary);

// Read the data from the website
while (InternetReadFile(hConnect, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
outFile.write(buffer, bytesRead);
}

// Cleanup
outFile.close();
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);

return true;
}

std::string
url_escape(const std::string &str) {
return encode(str, unreserved_chars);
}

std::string
url_get_host(const std::string &url) {
auto parsed = parse_uri(url);
if (!parsed) {
return "";
}
return parsed->host();
}

} // namespace http
10 changes: 7 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ if (TESTS_ENABLE_PYTHON_TESTS)
message(SEND_ERROR "Python not found, tests dependent on Python will be disabled")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=0)
endif ()
else()
else ()
message(STATUS "Python executable is set to ${TESTS_PYTHON_EXECUTABLE}")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=1)
list(APPEND TEST_DEFINITIONS TESTS_PYTHON_EXECUTABLE="${TESTS_PYTHON_EXECUTABLE}")
endif()
endif ()
else ()
message(STATUS "Python tests are disabled by 'TESTS_ENABLE_PYTHON_TESTS' option")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=0)
Expand Down Expand Up @@ -115,6 +115,10 @@ target_link_libraries(${PROJECT_NAME}
${PLATFORM_LIBRARIES})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${SUNSHINE_DEFINITIONS} ${TEST_DEFINITIONS})
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301
target_link_options(${PROJECT_NAME} PRIVATE)

if (MSYS OR MINGW)
target_link_directories(${PROJECT_NAME} PRIVATE "${CMAKE_BINARY_DIR}/lib")
target_link_options(${PROJECT_NAME} PRIVATE -lgtest_main)
endif ()

add_test(NAME ${PROJECT_NAME} COMMAND sunshine_test)
22 changes: 22 additions & 0 deletions tests/unit/test_httpcommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <gtest/gtest.h>

#include "src/httpcommon.h"

using namespace http;

TEST(HttpCommonTest, UrlEscape) {
ASSERT_EQ(url_escape("igdb_0123456789"), "igdb_0123456789");
ASSERT_EQ(url_escape("../../../"), "..%2F..%2F..%2F");
ASSERT_EQ(url_escape("..*\\"), "..%2A%5C");
}

TEST(HttpCommonTest, UrlGetHost) {
ASSERT_EQ(url_get_host("https://images.igdb.com/example.txt"), "images.igdb.com");
ASSERT_EQ(url_get_host("http://localhost:8080"), "localhost");
ASSERT_EQ(url_get_host("nonsense!!}{::"), "");
}

TEST(HttpCommonTest, DownloadFile) {
ASSERT_TRUE(download_file("https://httpbin.org/base64/aGVsbG8h", "hello.txt"));
ASSERT_TRUE(download_file("https://httpbin.org/redirect-to?url=/base64/aGVsbG8h", "hello-redirect.txt"));
}
Loading