123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- #ifndef CLIENT_GAMEMODE_H
- #define CLIENT_GAMEMODE_H
- #include <stdbool.h>
- #include <stdio.h>
- #include <dlfcn.h>
- #include <string.h>
- #include <assert.h>
- #include <sys/types.h>
- static char internal_gamemode_client_error_string[512] = { 0 };
- static volatile int internal_libgamemode_loaded = 1;
- typedef int (*api_call_return_int)(void);
- typedef const char *(*api_call_return_cstring)(void);
- typedef int (*api_call_pid_return_int)(pid_t);
- static api_call_return_int REAL_internal_gamemode_request_start = NULL;
- static api_call_return_int REAL_internal_gamemode_request_end = NULL;
- static api_call_return_int REAL_internal_gamemode_query_status = NULL;
- static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
- static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
- static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
- static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
- __attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
- void *handle, const char *name, void **out_func, size_t func_size, bool required)
- {
- void *symbol_lookup = NULL;
- char *dl_error = NULL;
-
- symbol_lookup = dlsym(handle, name);
- dl_error = dlerror();
- if (required && (dl_error || !symbol_lookup)) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "dlsym failed - %s",
- dl_error);
- return -1;
- }
-
- memcpy(out_func, &symbol_lookup, func_size);
- return 0;
- }
- __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
- {
-
- if (internal_libgamemode_loaded != 1) {
- return internal_libgamemode_loaded;
- }
-
- struct binding {
- const char *name;
- void **functor;
- size_t func_size;
- bool required;
- } bindings[] = {
- { "real_gamemode_request_start",
- (void **)&REAL_internal_gamemode_request_start,
- sizeof(REAL_internal_gamemode_request_start),
- true },
- { "real_gamemode_request_end",
- (void **)&REAL_internal_gamemode_request_end,
- sizeof(REAL_internal_gamemode_request_end),
- true },
- { "real_gamemode_query_status",
- (void **)&REAL_internal_gamemode_query_status,
- sizeof(REAL_internal_gamemode_query_status),
- false },
- { "real_gamemode_error_string",
- (void **)&REAL_internal_gamemode_error_string,
- sizeof(REAL_internal_gamemode_error_string),
- true },
- { "real_gamemode_request_start_for",
- (void **)&REAL_internal_gamemode_request_start_for,
- sizeof(REAL_internal_gamemode_request_start_for),
- false },
- { "real_gamemode_request_end_for",
- (void **)&REAL_internal_gamemode_request_end_for,
- sizeof(REAL_internal_gamemode_request_end_for),
- false },
- { "real_gamemode_query_status_for",
- (void **)&REAL_internal_gamemode_query_status_for,
- sizeof(REAL_internal_gamemode_query_status_for),
- false },
- };
- void *libgamemode = NULL;
-
- libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
- if (!libgamemode) {
-
- libgamemode = dlopen("libgamemode.so", RTLD_NOW);
- if (!libgamemode) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "dlopen failed - %s",
- dlerror());
- internal_libgamemode_loaded = -1;
- return -1;
- }
- }
-
- for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
- struct binding *binder = &bindings[i];
- if (internal_bind_libgamemode_symbol(libgamemode,
- binder->name,
- binder->functor,
- binder->func_size,
- binder->required)) {
- internal_libgamemode_loaded = -1;
- return -1;
- };
- }
-
- internal_libgamemode_loaded = 0;
- return 0;
- }
- __attribute__((always_inline)) static inline const char *gamemode_error_string(void)
- {
-
- if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
- return internal_gamemode_client_error_string;
- }
-
- assert(REAL_internal_gamemode_error_string != NULL);
- return REAL_internal_gamemode_error_string();
- }
- #ifdef GAMEMODE_AUTO
- __attribute__((constructor))
- #else
- __attribute__((always_inline)) static inline
- #endif
- int gamemode_request_start(void)
- {
-
- if (internal_load_libgamemode() < 0) {
- #ifdef GAMEMODE_AUTO
- fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
- #endif
- return -1;
- }
-
- assert(REAL_internal_gamemode_request_start != NULL);
- if (REAL_internal_gamemode_request_start() < 0) {
- #ifdef GAMEMODE_AUTO
- fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
- #endif
- return -1;
- }
- return 0;
- }
- #ifdef GAMEMODE_AUTO
- __attribute__((destructor))
- #else
- __attribute__((always_inline)) static inline
- #endif
- int gamemode_request_end(void)
- {
-
- if (internal_load_libgamemode() < 0) {
- #ifdef GAMEMODE_AUTO
- fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
- #endif
- return -1;
- }
-
- assert(REAL_internal_gamemode_request_end != NULL);
- if (REAL_internal_gamemode_request_end() < 0) {
- #ifdef GAMEMODE_AUTO
- fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
- #endif
- return -1;
- }
- return 0;
- }
- __attribute__((always_inline)) static inline int gamemode_query_status(void)
- {
-
- if (internal_load_libgamemode() < 0) {
- return -1;
- }
- if (REAL_internal_gamemode_query_status == NULL) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "gamemode_query_status missing (older host?)");
- return -1;
- }
- return REAL_internal_gamemode_query_status();
- }
- __attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
- {
-
- if (internal_load_libgamemode() < 0) {
- return -1;
- }
- if (REAL_internal_gamemode_request_start_for == NULL) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "gamemode_request_start_for missing (older host?)");
- return -1;
- }
- return REAL_internal_gamemode_request_start_for(pid);
- }
- __attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
- {
-
- if (internal_load_libgamemode() < 0) {
- return -1;
- }
- if (REAL_internal_gamemode_request_end_for == NULL) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "gamemode_request_end_for missing (older host?)");
- return -1;
- }
- return REAL_internal_gamemode_request_end_for(pid);
- }
- __attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
- {
-
- if (internal_load_libgamemode() < 0) {
- return -1;
- }
- if (REAL_internal_gamemode_query_status_for == NULL) {
- snprintf(internal_gamemode_client_error_string,
- sizeof(internal_gamemode_client_error_string),
- "gamemode_query_status_for missing (older host?)");
- return -1;
- }
- return REAL_internal_gamemode_query_status_for(pid);
- }
- #endif
|