Compare commits
3 Commits
0dd0706f52
...
0061edb3b2
Author | SHA1 | Date | |
---|---|---|---|
0061edb3b2 | |||
baeeceeaac | |||
211bf265ff |
@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
**2.3.12**
|
||||
* Media Layer Proxy Optimizations
|
||||
* Bug Fixes
|
||||
|
||||
**2.3.11**
|
||||
* ``--version`` Command Line Option
|
||||
* TPS Measured In Benchmark & Server
|
||||
|
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
@ -254,6 +254,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Fix MCPI Dependencies
|
||||
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
|
||||
{
|
||||
// Log
|
||||
DEBUG("Patching ELF Dependencies...");
|
||||
@ -273,7 +274,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
#endif
|
||||
|
||||
// Patch
|
||||
patch_mcpi_elf_dependencies(resolved_path, linker);
|
||||
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path, linker);
|
||||
|
||||
// Free Linker Path
|
||||
if (linker != NULL) {
|
||||
@ -281,7 +282,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Verify
|
||||
if (!starts_with(getenv("MCPI_EXECUTABLE_PATH"), "/tmp")) {
|
||||
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
}
|
||||
@ -391,7 +392,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
new_args[argv_start + argc] = NULL;
|
||||
|
||||
// Set Executable Argument
|
||||
new_args[argv_start] = getenv("MCPI_EXECUTABLE_PATH");
|
||||
new_args[argv_start] = new_mcpi_exe_path;
|
||||
|
||||
// Non-ARM Systems Need QEMU
|
||||
#ifndef __ARM_ARCH
|
||||
|
@ -8,23 +8,21 @@
|
||||
#include "patchelf.h"
|
||||
|
||||
// Duplicate MCPI Executable Into /tmp
|
||||
#define TMP_DIR "/tmp/.minecraft-pi-patched"
|
||||
static void duplicate_mcpi_executable(const char *original_path) {
|
||||
static void duplicate_mcpi_executable(const char *original_path, char *new_path) {
|
||||
// Ensure Temporary Directory
|
||||
{
|
||||
// Check If It Exists
|
||||
struct stat tmp_stat;
|
||||
int exists = stat(TMP_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
|
||||
int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
|
||||
if (!exists) {
|
||||
// Doesn't Exist
|
||||
if (mkdir(TMP_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
|
||||
if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
|
||||
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate New File
|
||||
char new_path[] = TMP_DIR "/XXXXXX";
|
||||
int new_file_fd = mkstemp(new_path);
|
||||
if (new_file_fd == -1) {
|
||||
ERR("Unable To Create Temporary File: %s", strerror(errno));
|
||||
@ -33,7 +31,6 @@ static void duplicate_mcpi_executable(const char *original_path) {
|
||||
if (new_file == NULL) {
|
||||
ERR("Unable To Open Temporary File: %s", strerror(errno));
|
||||
}
|
||||
set_and_print_env("MCPI_EXECUTABLE_PATH", new_path);
|
||||
|
||||
// Copy Original File
|
||||
{
|
||||
@ -76,7 +73,7 @@ static void duplicate_mcpi_executable(const char *original_path) {
|
||||
"--remove-needed", "libX11.so.6", \
|
||||
"--remove-needed", "libEGL.so", \
|
||||
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1", \
|
||||
exe, \
|
||||
new_path, \
|
||||
NULL \
|
||||
}; \
|
||||
int _macro_return_code = 0; \
|
||||
@ -86,12 +83,9 @@ static void duplicate_mcpi_executable(const char *original_path) {
|
||||
} \
|
||||
_macro_return_code; \
|
||||
})
|
||||
void patch_mcpi_elf_dependencies(const char *original_path, const char *linker) {
|
||||
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) {
|
||||
// Duplicate MCPI executable into /tmp so it can be modified.
|
||||
duplicate_mcpi_executable(original_path);
|
||||
|
||||
// Get Path
|
||||
char *exe = getenv("MCPI_EXECUTABLE_PATH");
|
||||
duplicate_mcpi_executable(original_path, new_path);
|
||||
|
||||
// Run patchelf
|
||||
int return_code;
|
||||
@ -107,8 +101,8 @@ void patch_mcpi_elf_dependencies(const char *original_path, const char *linker)
|
||||
}
|
||||
|
||||
// Fix Permissions
|
||||
if (chmod(exe, S_IRUSR | S_IXUSR) != 0) {
|
||||
ERR("Unable To Set File Permissions: %s: %s", exe, strerror(errno));
|
||||
if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) {
|
||||
ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void patch_mcpi_elf_dependencies(const char *original_path, const char *linker);
|
||||
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
|
||||
|
||||
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker);
|
||||
char *patch_get_interpreter(const char *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -6,6 +6,7 @@ extern "C" {
|
||||
|
||||
#define GL_FALSE 0
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_FLOAT 0x1406
|
||||
|
@ -39,6 +39,21 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
#define CALL_GL_POINTER(unique_id, name) \
|
||||
CALL(unique_id, name, void, (GLint size, GLenum type, GLsizei stride, const void *pointer)) { \
|
||||
/* Check */ \
|
||||
static int last_set = 0; \
|
||||
static GLint last_size; \
|
||||
static GLenum last_type; \
|
||||
static GLsizei last_stride; \
|
||||
static const void *last_pointer; \
|
||||
if (last_set && last_size == size && last_type == type && last_stride == stride && last_pointer == pointer) { \
|
||||
return; \
|
||||
} else { \
|
||||
last_set = 1; \
|
||||
last_size = size; \
|
||||
last_type = type; \
|
||||
last_stride = stride; \
|
||||
last_pointer = pointer; \
|
||||
} \
|
||||
/* Lock Proxy */ \
|
||||
start_proxy_call(); \
|
||||
\
|
||||
@ -107,6 +122,31 @@ CALL(14, glBlendFunc, void, (GLenum sfactor, GLenum dfactor)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Track Bindings
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
static GLuint bound_buffer = 0;
|
||||
static GLuint bound_texture = 0;
|
||||
static unsigned char vertex_array_enabled = 0;
|
||||
static unsigned char color_array_enabled = 0;
|
||||
static unsigned char tex_coord_array_enabled = 0;
|
||||
static unsigned char *get_array_enabled_pointer(GLenum array) {
|
||||
switch (array) {
|
||||
case GL_VERTEX_ARRAY: {
|
||||
return &vertex_array_enabled;
|
||||
}
|
||||
case GL_COLOR_ARRAY: {
|
||||
return &color_array_enabled;
|
||||
}
|
||||
case GL_TEXTURE_COORD_ARRAY: {
|
||||
return &tex_coord_array_enabled;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Array Pointer: %i", array);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
@ -116,6 +156,13 @@ CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
|
||||
write_int((uint32_t) mode);
|
||||
write_int((uint32_t) first);
|
||||
write_int((uint32_t) count);
|
||||
write_int(bound_buffer);
|
||||
write_int(bound_texture);
|
||||
if (!vertex_array_enabled) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
write_byte(color_array_enabled);
|
||||
write_byte(tex_coord_array_enabled);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
@ -123,7 +170,17 @@ CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
|
||||
GLenum mode = (GLenum) read_int();
|
||||
GLint first = (GLint) read_int();
|
||||
GLsizei count = (GLsizei) read_int();
|
||||
GLuint bound_buffer = (GLuint) read_int();
|
||||
GLuint bound_texture = (GLuint) read_int();
|
||||
unsigned char color_array_enabled = read_byte();
|
||||
unsigned char tex_coord_array_enabled = read_byte();
|
||||
// Run
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bound_buffer);
|
||||
glBindTexture(GL_TEXTURE_2D, bound_texture);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
#define set_array_enabled(condition, enum) condition ? glEnableClientState(enum) : glDisableClientState(enum);
|
||||
set_array_enabled(color_array_enabled, GL_COLOR_ARRAY);
|
||||
set_array_enabled(tex_coord_array_enabled, GL_TEXTURE_COORD_ARRAY);
|
||||
glDrawArrays(mode, first, count);
|
||||
#endif
|
||||
}
|
||||
@ -187,6 +244,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
|
||||
write_int((uint32_t) target);
|
||||
write_int((uint32_t) size);
|
||||
write_int((uint32_t) usage);
|
||||
write_int(bound_buffer);
|
||||
// Write Data
|
||||
unsigned char is_null = data == NULL;
|
||||
write_byte(is_null);
|
||||
@ -200,6 +258,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
|
||||
GLenum target = (GLenum) read_int();
|
||||
GLsizeiptr size = (GLsizeiptr) read_int();
|
||||
GLenum usage = (GLenum) read_int();
|
||||
GLuint bound_buffer = (GLuint) read_int();
|
||||
// Load Data
|
||||
void *data = NULL;
|
||||
unsigned char is_null = read_byte();
|
||||
@ -223,6 +282,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
|
||||
safe_read(data, (size_t) size);
|
||||
}
|
||||
// Run
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bound_buffer);
|
||||
glBufferData(target, size, data, usage);
|
||||
#endif
|
||||
}
|
||||
@ -316,6 +376,7 @@ CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) {
|
||||
write_int((uint32_t) target);
|
||||
write_int((uint32_t) pname);
|
||||
write_int((uint32_t) param);
|
||||
write_int(bound_texture);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
@ -323,7 +384,9 @@ CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) {
|
||||
GLenum target = (GLenum) read_int();
|
||||
GLenum pname = (GLenum) read_int();
|
||||
GLint param = (GLint) read_int();
|
||||
GLuint bound_texture = (GLuint) read_int();
|
||||
// Run
|
||||
glBindTexture(GL_TEXTURE_2D, bound_texture);
|
||||
glTexParameteri(target, pname, param);
|
||||
#endif
|
||||
}
|
||||
@ -383,6 +446,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
|
||||
write_int((uint32_t) border);
|
||||
write_int((uint32_t) format);
|
||||
write_int((uint32_t) type);
|
||||
write_int(bound_texture);
|
||||
write_byte(is_null);
|
||||
if (!is_null) {
|
||||
safe_write((void *) pixels, (size_t) size);
|
||||
@ -399,6 +463,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
|
||||
GLint border = (GLint) read_int();
|
||||
GLenum format = (GLenum) read_int();
|
||||
GLenum type = (GLenum) read_int();
|
||||
GLuint bound_texture = (GLuint) read_int();
|
||||
unsigned char is_null = read_byte();
|
||||
void *pixels = NULL;
|
||||
if (!is_null) {
|
||||
@ -408,6 +473,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
|
||||
safe_read(pixels, (size_t) size);
|
||||
}
|
||||
// Run
|
||||
glBindTexture(GL_TEXTURE_2D, bound_texture);
|
||||
glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
// Free
|
||||
if (!is_null) {
|
||||
@ -433,22 +499,17 @@ CALL(26, glEnable, void, (GLenum cap)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(27, glEnableClientState, void, (GLenum array)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_int((uint32_t) array);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
GLenum array = (GLenum) read_int();
|
||||
// Run
|
||||
glEnableClientState(array);
|
||||
#endif
|
||||
void glEnableClientState(GLenum array) {
|
||||
// Set
|
||||
unsigned char *enabled = get_array_enabled_pointer(array);
|
||||
if (*enabled) {
|
||||
return;
|
||||
} else {
|
||||
*enabled = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
@ -469,22 +530,17 @@ CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(29, glDisableClientState, void, (GLenum array)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_int((uint32_t) array);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
GLenum array = (GLenum) read_int();
|
||||
// Run
|
||||
glDisableClientState(array);
|
||||
#endif
|
||||
void glDisableClientState(GLenum array) {
|
||||
// Set
|
||||
unsigned char *enabled = get_array_enabled_pointer(array);
|
||||
if (!*enabled) {
|
||||
return;
|
||||
} else {
|
||||
*enabled = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
@ -522,24 +578,16 @@ CALL(31, glDepthFunc, void, (GLenum func)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(32, glBindBuffer, void, (GLenum target, GLuint buffer)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_int((uint32_t) target);
|
||||
write_int((uint32_t) buffer);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
GLenum target = (GLenum) read_int();
|
||||
GLuint buffer = (GLuint) read_int();
|
||||
// Run
|
||||
glBindBuffer(target, buffer);
|
||||
#endif
|
||||
void glBindBuffer(GLenum target, GLuint buffer) {
|
||||
// Set
|
||||
if (target == GL_ARRAY_BUFFER) {
|
||||
bound_buffer = buffer;
|
||||
} else {
|
||||
PROXY_ERR("Unsupported Buffer Binding: %u", target);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
@ -748,6 +796,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
|
||||
write_int((uint32_t) height);
|
||||
write_int((uint32_t) format);
|
||||
write_int((uint32_t) type);
|
||||
write_int(bound_texture);
|
||||
write_byte(is_null);
|
||||
if (!is_null) {
|
||||
safe_write((void *) pixels, (size_t) size);
|
||||
@ -764,6 +813,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
|
||||
GLsizei height = (GLsizei) read_int();
|
||||
GLenum format = (GLenum) read_int();
|
||||
GLenum type = (GLenum) read_int();
|
||||
GLuint bound_texture = (GLuint) read_int();
|
||||
unsigned char is_null = read_byte();
|
||||
void *pixels = NULL;
|
||||
if (!is_null) {
|
||||
@ -773,6 +823,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
|
||||
safe_read(pixels, (size_t) size);
|
||||
}
|
||||
// Run
|
||||
glBindTexture(GL_TEXTURE_2D, bound_texture);
|
||||
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
// Free
|
||||
if (!is_null) {
|
||||
@ -887,24 +938,16 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(49, glBindTexture, void, (GLenum target, GLuint texture)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_int((uint32_t) target);
|
||||
write_int((uint32_t) texture);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
GLenum target = (GLenum) read_int();
|
||||
GLuint texture = (GLuint) read_int();
|
||||
// Run
|
||||
glBindTexture(target, texture);
|
||||
#endif
|
||||
void glBindTexture(GLenum target, GLuint texture) {
|
||||
// Set
|
||||
if (target == GL_TEXTURE_2D) {
|
||||
bound_texture = texture;
|
||||
} else {
|
||||
PROXY_ERR("Unsupported Texture Binding: %u", target);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
|
@ -9,18 +9,15 @@
|
||||
#include "../common/common.h"
|
||||
|
||||
// Store Handlers
|
||||
__attribute__((const)) static std::vector<proxy_handler_t> &get_handlers() {
|
||||
static std::vector<proxy_handler_t> handlers;
|
||||
return handlers;
|
||||
}
|
||||
static std::vector<proxy_handler_t> handlers;
|
||||
void _add_handler(unsigned char unique_id, proxy_handler_t handler) {
|
||||
if (get_handlers().size() > unique_id && get_handlers()[unique_id] != NULL) {
|
||||
if (handlers.size() > unique_id && handlers[unique_id] != NULL) {
|
||||
PROXY_ERR("Duplicate ID: %i", (int) unique_id);
|
||||
}
|
||||
if (get_handlers().size() <= unique_id) {
|
||||
get_handlers().resize(unique_id + 1);
|
||||
if (handlers.size() <= unique_id) {
|
||||
handlers.resize(unique_id + 1);
|
||||
}
|
||||
get_handlers()[unique_id] = handler;
|
||||
handlers[unique_id] = handler;
|
||||
}
|
||||
|
||||
// Store Parent PID
|
||||
@ -48,10 +45,7 @@ static void exit_handler(__attribute__((unused)) int signal_id) {
|
||||
// Main
|
||||
int main(int argc, char *argv[]) {
|
||||
// Install Signal Handlers
|
||||
struct sigaction act_sigint;
|
||||
memset((void *) &act_sigint, 0, sizeof (struct sigaction));
|
||||
act_sigint.sa_handler = &exit_handler;
|
||||
sigaction(SIGINT, &act_sigint, NULL);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
struct sigaction act_sigterm;
|
||||
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
|
||||
act_sigterm.sa_handler = &exit_handler;
|
||||
@ -84,9 +78,9 @@ int main(int argc, char *argv[]) {
|
||||
int running = is_connection_open();
|
||||
while (running && !exit_requested) {
|
||||
unsigned char unique_id = read_byte();
|
||||
if (get_handlers().size() > unique_id && get_handlers()[unique_id] != NULL) {
|
||||
if (handlers.size() > unique_id && handlers[unique_id] != NULL) {
|
||||
// Run Method
|
||||
get_handlers()[unique_id]();
|
||||
handlers[unique_id]();
|
||||
// Check If Connection Is Still Open
|
||||
if (!is_connection_open()) {
|
||||
// Exit
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@ -12,23 +14,76 @@
|
||||
PROXY_ERR("Attempting To Access Closed Connection"); \
|
||||
} \
|
||||
}
|
||||
// Buffer Reads
|
||||
static void *_read_cache = NULL;
|
||||
__attribute__((destructor)) static void _free_read_cache() {
|
||||
if (_read_cache != NULL) {
|
||||
free(_read_cache);
|
||||
}
|
||||
}
|
||||
static size_t _read_cache_size = 0;
|
||||
static size_t _read_cache_actual_size = 0;
|
||||
static size_t _read_cache_position = 0;
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
void safe_read(void *buf, size_t len) {
|
||||
// Check Data
|
||||
if (buf == NULL) {
|
||||
PROXY_ERR("Attempting To Read Into NULL Buffer");
|
||||
}
|
||||
// Setup
|
||||
size_t to_read = len;
|
||||
// Copy From Read Buffer
|
||||
if (_read_cache != NULL && _read_cache_size > 0) {
|
||||
char *read_cache = (void *) (((unsigned char *) _read_cache) + _read_cache_position);
|
||||
size_t read_cache_size = _read_cache_size - _read_cache_position;
|
||||
if (read_cache_size > 0) {
|
||||
size_t to_copy = min(to_read, read_cache_size);
|
||||
memcpy(buf, read_cache, to_copy);
|
||||
to_read -= to_copy;
|
||||
_read_cache_position += to_copy;
|
||||
}
|
||||
}
|
||||
// Check If Done
|
||||
if (to_read < 1) {
|
||||
return;
|
||||
}
|
||||
if (_read_cache_position < _read_cache_size) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
// Flush Write Cache
|
||||
flush_write_cache();
|
||||
// Read
|
||||
size_t to_read = len;
|
||||
while (to_read > 0) {
|
||||
// Read Remaining Data
|
||||
size_t to_read_to_cache = 0;
|
||||
while (to_read_to_cache < 1) {
|
||||
int bytes_available;
|
||||
if (ioctl(get_connection_read(), FIONREAD, &bytes_available) == -1) {
|
||||
bytes_available = 0;
|
||||
}
|
||||
to_read_to_cache = max((size_t) bytes_available, to_read);
|
||||
}
|
||||
// Resize Buffer
|
||||
_read_cache_position = 0;
|
||||
_read_cache_size = to_read_to_cache;
|
||||
if (_read_cache == NULL) {
|
||||
_read_cache_actual_size = _read_cache_size;
|
||||
_read_cache = malloc(_read_cache_actual_size);
|
||||
} else if (_read_cache_size > _read_cache_actual_size) {
|
||||
_read_cache_actual_size = _read_cache_size;
|
||||
_read_cache = realloc(_read_cache, _read_cache_actual_size);
|
||||
}
|
||||
ALLOC_CHECK(_read_cache);
|
||||
// Read Into Buffer
|
||||
while (to_read_to_cache > 0) {
|
||||
CHECK_CONNECTION();
|
||||
ssize_t x = read(get_connection_read(), (void *) (((unsigned char *) buf) + (len - to_read)), to_read);
|
||||
ssize_t x = read(get_connection_read(), (void *) (((unsigned char *) _read_cache) + (_read_cache_size - to_read_to_cache)), to_read_to_cache);
|
||||
if (x == -1 && errno != EINTR) {
|
||||
PROXY_ERR("Failed Reading Data To Connection: %s", strerror(errno));
|
||||
}
|
||||
to_read -= x;
|
||||
to_read_to_cache -= x;
|
||||
}
|
||||
// Copy Remaining Data
|
||||
safe_read((void *) (((unsigned char *) buf) + (len - to_read)), to_read);
|
||||
}
|
||||
// Buffer Writes
|
||||
static void *_write_cache = NULL;
|
||||
|
@ -86,6 +86,34 @@ static void start_media_layer_proxy_client(int read, int write) {
|
||||
update_client_state(1, 0);
|
||||
}
|
||||
|
||||
// Maximize Pipe Buffer Size
|
||||
static void maximize_pipe_fd_size(int fd) {
|
||||
// Read Maximum Pipe Size
|
||||
std::ifstream max_size_file("/proc/sys/fs/pipe-max-size");
|
||||
if (!max_size_file.good()) {
|
||||
PROXY_ERR("%s", "Unable To Open Maximum Pipe Size File");
|
||||
}
|
||||
// Read One Line
|
||||
int max_size;
|
||||
std::string line;
|
||||
if (std::getline(max_size_file, line) && line.size() > 0) {
|
||||
max_size = std::stoi(line);
|
||||
} else {
|
||||
PROXY_ERR("%s", "Unable To Read Maximum Pipe Size File");
|
||||
}
|
||||
// Close
|
||||
max_size_file.close();
|
||||
// Set Maximum Pipe Size
|
||||
errno = 0;
|
||||
if (fcntl(fd, F_SETPIPE_SZ, max_size) < max_size) {
|
||||
PROXY_ERR("Unable To Set Maximum Pipe Size: %s", errno != 0 ? strerror(errno) : "Unknown Error");
|
||||
}
|
||||
}
|
||||
static void maximize_pipe_size(int pipe[2]) {
|
||||
maximize_pipe_fd_size(pipe[0]);
|
||||
maximize_pipe_fd_size(pipe[1]);
|
||||
}
|
||||
|
||||
// Start Server
|
||||
static int loaded = 0;
|
||||
__attribute__((constructor)) void media_ensure_loaded() {
|
||||
@ -98,8 +126,10 @@ __attribute__((constructor)) void media_ensure_loaded() {
|
||||
// Create Connection
|
||||
int server_to_client_pipe[2];
|
||||
safe_pipe2(server_to_client_pipe, 0);
|
||||
maximize_pipe_size(server_to_client_pipe);
|
||||
int client_to_server_pipe[2];
|
||||
safe_pipe2(client_to_server_pipe, 0);
|
||||
maximize_pipe_size(client_to_server_pipe);
|
||||
// Set Connection
|
||||
set_connection(client_to_server_pipe[0], server_to_client_pipe[1]);
|
||||
|
||||
|
@ -133,13 +133,18 @@ void init_compat() {
|
||||
__attribute__((destructor)) static void cleanup_temporary() {
|
||||
// Cleanup Executable
|
||||
{
|
||||
const char *exe = getenv("MCPI_EXECUTABLE_PATH");
|
||||
// Check If Executable Is Temporary
|
||||
if (exe != NULL && starts_with(exe, "/tmp")) {
|
||||
// Cleanup Temporary File
|
||||
if (unlink(exe) != 0) {
|
||||
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
|
||||
char *exe = realpath("/proc/self/exe", NULL);
|
||||
// Check If Successful
|
||||
if (exe != NULL) {
|
||||
// Check If Executable Is Temporary
|
||||
if (starts_with(exe, "/tmp")) {
|
||||
// Cleanup Temporary File
|
||||
if (unlink(exe) != 0) {
|
||||
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
// Free
|
||||
free(exe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ if (mode === 'client') {
|
||||
'libgtk-3-0',
|
||||
'libglib2.0-0',
|
||||
'libgdk-pixbuf2.0-0',
|
||||
'librsvg2-common',
|
||||
'shared-mime-info',
|
||||
'libfreeimage3',
|
||||
'libopenal1'
|
||||
@ -59,7 +60,8 @@ const packageExclusions = [
|
||||
'librest-*',
|
||||
'libcups2',
|
||||
'libcolord2',
|
||||
'libmount1'
|
||||
'libmount1',
|
||||
'libwayland-*'
|
||||
];
|
||||
|
||||
// APT
|
||||
|
Loading…
Reference in New Issue
Block a user