Skip to content

Commit

Permalink
geode web utils suck!!!
Browse files Browse the repository at this point in the history
  • Loading branch information
dankmeme01 committed Dec 7, 2023
1 parent 43bfbb6 commit 337c91b
Show file tree
Hide file tree
Showing 27 changed files with 677 additions and 183 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@ server/game/flamegraph.svg
server/game/perf.data
server/game/perf.data.old
server/game/test-flamegraph.sh
server/game/test-bench.sh
server/game/test-bench.sh

libs/openssl
31 changes: 21 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden)
project(globed2 VERSION 1.0.0)

option(ENABLE_DEBUG "Debug mode" OFF)
if (ENABLE_DEBUG)
if (ENABLE_DEBUG OR CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(GLOBED_DEBUG=1)
add_compile_definitions(GEODE_DEBUG=1)
else()
# Enable LTO in release (2.5x less binary size, no noticable compile time hit)
# Enable LTO in release (2.5x less binary size, costs only a few extra seconds of build time)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

Expand All @@ -29,18 +30,13 @@ if (CMAKE_HOST_SYSTEM MATCHES "Linux" AND CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_compile_options("-march=skylake")
endif()

# enable exceptions on android
# enable exceptions on android (this doesn't work !!!!!!! fix me!!!)
if (ANDROID)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
endif()

add_library(${PROJECT_NAME} SHARED ${SOURCES})

# enable extra warnings
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-compat -Wno-c++14-compat -Wno-c++17-compat -Wno-old-style-cast -Wno-implicit-int-float-conversion -Wno-global-constructors -Wno-pre-c++20-compat-pedantic -Wno-exit-time-destructors -Wno-reserved-identifier -Wno-reserved-macro-identifier -Wno-dollar-in-identifier-extension -Wno-ctad-maybe-unsupported -Wno-unsafe-buffer-usage -Wno-newline-eof -Wno-shadow -Wno-inconsistent-missing-destructor-override -Wno-float-conversion -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-suggest-override -Wno-overloaded-virtual -Wno-unused-parameter -Wno-undefined-func-template -Wno-non-virtual-dtor -Wno-sign-compare -Wno-header-hygiene)
endif()

if (NOT DEFINED ENV{GEODE_SDK})
message(FATAL_ERROR "Unable to find Geode SDK! Please define GEODE_SDK environment variable to point to Geode")
else()
Expand All @@ -52,13 +48,28 @@ add_subdirectory($ENV{GEODE_SDK} ${CMAKE_CURRENT_BINARY_DIR}/geode)
# done so you can include root files with <file.hpp>
target_include_directories(${PROJECT_NAME} PRIVATE src/)

# libcurl ssl support
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
# on windows we just use schannel, no extra setup
set(CURL_USE_SCHANNEL ON)
set(CURL_USE_OPENSSL OFF)
elseif(ANDROID)
# on android we use geode provided openssl library and our own headers
set(CURL_USE_SCHANNEL OFF)
set(CURL_USE_OPENSSL ON)
set(OPENSSL_ROOT_DIR "${CMAKE_SOURCE_DIR}/libs/openssl")
set(OPENSSL_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/libs/openssl/include")
set(OPENSSL_CRYPTO_LIBRARY "$ENV{GEODE_SDK}/loader/include/link/android/libcrypto.a")
set(OPENSSL_SSL_LIBRARY "$ENV{GEODE_SDK}/loader/include/link/android/libssl.a")
endif()

# our favorite libraries
CPMAddPackage("gh:camila314/UIBuilder#main")
CPMAddPackage("gh:xiph/opus#master")
CPMAddPackage("gh:dankmeme01/libsodium-cmake#master")
CPMAddPackage("gh:curl/curl#curl-8_5_0")

# TODO suppress -Wpointer-sign from libsodium
target_link_libraries(${PROJECT_NAME} UIBuilder opus sodium)
target_link_libraries(${PROJECT_NAME} UIBuilder opus sodium libcurl)

# link to fmod on android
if (ANDROID)
Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Known issues:

See the [server readme](./server/readme.md) for more information about the server and how you can host it.

## Building

Building is the same as building any other Geode mod, except for Android. If you want to build the mod for Android, see the [android build readme](./android-build.md) for instructions on how to do it.

## Credit

ca7x3, Firee, Croozington, Coloride, Cvolton, mat, alk, maki, xTymon - thank you for being awesome, whether it's because you helped me directly, suggested ideas, helped with testing, or if I just found you awesome in general :D
Expand All @@ -42,7 +46,8 @@ RobTop - thank you for releasing this awesome game :)

Globed is licensed under the MIT license. All of the following libraries used in Globed have their own licenses you may want to read:

* [Geode](https://geode-sdk.org/) - [BSL 1.0](https://github.com/geode-sdk/geode/blob/main/LICENSE.txt)
* [UIBuilder](https://github.com/camila314/uibuilder) - [MIT](https://github.com/camila314/uibuilder/blob/main/LICENSE)
* [Opus](https://github.com/xiph/opus) - [BSD 3-Clause (?)](https://github.com/xiph/opus/blob/master/COPYING)
* [libsodium](https://github.com/jedisct1/libsodium) - [ISC](https://github.com/jedisct1/libsodium/blob/master/LICENSE)
* Geode - [website](https://geode-sdk.org) - [repository](https://github.com/geode-sdk/geode) - [license](https://github.com/geode-sdk/geode/blob/main/LICENSE.txt)
* UIBuilder - [repository](https://github.com/camila314/uibuilder) - [license](https://github.com/camila314/uibuilder/blob/main/LICENSE)
* Opus - [website](https://opus-codec.org/) - [repository](https://github.com/xiph/opus) - [license](https://github.com/xiph/opus/blob/master/COPYING)
* libsodium - [website](https://libsodium.gitbook.io/doc/) - [repository](https://github.com/jedisct1/libsodium) - [license](https://github.com/jedisct1/libsodium/blob/master/LICENSE)
* Curl - [website](https://curl.se/) - [repository](https://github.com/curl/curl) - [license](https://curl.se/docs/copyright.html)
35 changes: 35 additions & 0 deletions android-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## android building

first it's time to clone openssl:

```sh
cd libs/
git clone https://github.com/openssl/openssl.git
cd openssl
```

then you want to configure it:

```sh
export NDK_HOME=/opt/android-ndk # set path to your ndk if it's different
PATH=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64:$PATH ./Configure android-arm -D__ANDROID_API__=24
```

then you want to build it, BUT keep in mind there's no need to build the whole thing. all you want is for codegen to run, you won't need the actual built libraries as they are already provided by geode.

```sh
make
```

after you stop seeing lines that look similar to these:

```sh
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" "-oMakefile" include/openssl/x509.h.in > include/openssl/x509.h
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" "-oMakefile" include/openssl/x509_vfy.h.in > include/openssl/x509_vfy.h
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" "-oMakefile" include/openssl/x509v3.h.in > include/openssl/x509v3.h
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" "-oMakefile" test/provider_internal_test.cnf.in > test/provider_internal_test.cnf
```

you can Ctrl+C and stop the build. **If `make` fails and shows an error, that is fine! As long as the headers were generated properly, there is no need to worry.**

after that's done you just proceed to build the mod like any other android mod. **make sure to set minimum SDK version to 24, or you will get linker errors!**
5 changes: 3 additions & 2 deletions src/data/bytebuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ class ByteBuffer {
// Write an enum
template <typename E>
void writeEnum(const E& val) {
using P = std::underlying_type<E>::type;
// macos clang is so fire
using P = typename std::underlying_type<E>::type;
static_assert(util::data::IsPrimitive<P>, "enum underlying type must be a primitive");

this->writePrimitive<P>(static_cast<P>(val));
Expand All @@ -294,7 +295,7 @@ class ByteBuffer {
// TODO no validation, likely not planning to add but still important to know
template <typename E>
E readEnum() {
using P = std::underlying_type<E>::type;
using P = typename std::underlying_type<E>::type;
static_assert(util::data::IsPrimitive<P>, "enum underlying type must be a primitive");

return static_cast<E>(this->readPrimitive<P>());
Expand Down
4 changes: 4 additions & 0 deletions src/managers/central_server_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ std::optional<CentralServer> CentralServerManager::getActive() {
return servers->at(idx);
}

int CentralServerManager::getActiveIndex() {
return _activeIdx.load();
}

std::vector<CentralServer> CentralServerManager::getAllServers() {
return *_servers.lock();
}
Expand Down
1 change: 1 addition & 0 deletions src/managers/central_server_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class CentralServerManager {
void setActive(int index);
// get the current active server, thread safe
std::optional<CentralServer> getActive();
int getActiveIndex();

// get all central servers, thread safe
std::vector<CentralServer> getAllServers();
Expand Down
2 changes: 1 addition & 1 deletion src/managers/game_server_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ size_t GameServerManager::count() {
return _data.lock()->servers.size();
}

void GameServerManager::setActive(const std::string id) {
void GameServerManager::setActive(const std::string& id) {
auto data = _data.lock();
data->active = id;
}
Expand Down
2 changes: 1 addition & 1 deletion src/managers/game_server_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class GameServerManager {
void clear();
size_t count();

void setActive(const std::string id);
void setActive(const std::string& id);
std::string active();
void clearActive();

Expand Down
117 changes: 117 additions & 0 deletions src/net/http/client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "client.hpp"

#include <util/time.hpp>

GLOBED_SINGLETON_DEF(GHTTPClient)

GHTTPClient::GHTTPClient() {
curl = curl_easy_init();
GLOBED_REQUIRE(curl != nullptr, "cURL failed to initialize")

threadHandle = std::thread(&GHTTPClient::threadFunc, this);
}

GHTTPClient::~GHTTPClient() {
_running = false;
if (threadHandle.joinable()) threadHandle.join();

if (curl) {
curl_easy_cleanup(curl);
curl = nullptr;
}

geode::log::debug("HTTP client thread halted");
}

void GHTTPClient::send(GHTTPRequestHandle request) {
requests.push(request);
}

void GHTTPClient::threadFunc() {
while (_running) {
if (!requests.waitForMessages(util::time::secs(1))) continue;

auto request = requests.pop();
auto response = this->performRequest(request);

geode::Loader::get()->queueInMainThread([response, request] {
request.maybeCallback(response);
});
}
}

static size_t writeCallback(void* contents, size_t size, size_t nmemb, std::ostringstream* stream) {
size_t totalSize = size * nmemb;
*stream << std::string(static_cast<char*>(contents), totalSize);
return totalSize;
}

GHTTPResponse GHTTPClient::performRequest(GHTTPRequestHandle handle) {
GHTTPResponse response;

GHTTPRequest& req = *handle.handle.get();

// clear leftover data from previous request
curl_easy_reset(curl);

switch (req.rType) {
case GHTTPRequestType::GET:
break;
case GHTTPRequestType::POST:
curl_easy_setopt(curl, CURLOPT_POST, 1L);
break;
case GHTTPRequestType::PUT:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
break;
case GHTTPRequestType::DELETE_:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
break;
}

if (!req.rData.empty()) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req.rData.c_str());
}

curl_easy_setopt(curl, CURLOPT_USERAGENT, req.rUserAgent.c_str());
curl_easy_setopt(curl, CURLOPT_URL, req.rUrl.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, req.rFollowRedirects);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, (long)req.rTimeout);

// security is for nerds
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

// http headers
struct curl_slist* headerList = nullptr;
if (!req.rHeaders.empty()) {
for (const auto& header: req.rHeaders) {
headerList = curl_slist_append(headerList, header.c_str());
}

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
}

std::ostringstream ss;

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ss);

response.resCode = curl_easy_perform(curl);
response.failed = response.resCode != CURLE_OK;

if (response.failed) {
response.failMessage = curl_easy_strerror(response.resCode);
} else {
long httpCode;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);

response.statusCode = httpCode;
response.response = ss.str();
}

if (headerList != nullptr) {
curl_slist_free_all(headerList);
}

return response;
}
28 changes: 28 additions & 0 deletions src/net/http/client.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once
#include <defs.hpp>

#include <queue>
#include <thread>

#include "request.hpp"
#include <util/sync.hpp>

class GHTTPClient {
GLOBED_SINGLETON(GHTTPClient)
GHTTPClient();
~GHTTPClient();

// add the request to the queue of pending requests
void send(GHTTPRequestHandle request);

protected:
CURL* curl;
std::thread threadHandle;

util::sync::AtomicBool _running = true;
util::sync::SmartMessageQueue<GHTTPRequestHandle> requests;

void threadFunc();

GHTTPResponse performRequest(GHTTPRequestHandle req);
};
Loading

0 comments on commit 337c91b

Please sign in to comment.