Skip to content

Commit

Permalink
rm2fb: Use unistdpp in SharedBuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
timower committed Dec 2, 2023
1 parent bf35543 commit edc022d
Show file tree
Hide file tree
Showing 18 changed files with 170 additions and 102 deletions.
1 change: 1 addition & 0 deletions libs/rMlib/include/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <unistdpp/error.h>

#include <iostream>
#include <string>

#include <tl/expected.hpp>
Expand Down
4 changes: 2 additions & 2 deletions libs/rm2fb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pkg_check_modules(SYSTEMD libsystemd REQUIRED)
add_library(rm2fb_lib STATIC
SharedBuffer.cpp
ControlSocket.cpp
ImageHook.cpp
InputDevice.cpp
Versions/Version.cpp
Versions/Version2.15.cpp
Expand All @@ -36,13 +35,14 @@ target_link_libraries(rm2fb_lib
unistdpp
${LIBEVDEV_LIBRARIES})

add_library(rm2fb_server SHARED Server.cpp)
add_library(rm2fb_server SHARED Server.cpp ImageHook.cpp)
target_link_libraries(rm2fb_server PRIVATE rm2fb_lib ${SYSTEMD_LIBRARIES})
target_include_directories(rm2fb_server PRIVATE ${SYSTEMD_INCLUDE_DIRS})

add_library(rm2fb_client SHARED
Client.cpp
IOCTL.cpp
ImageHook.cpp
AddressHooking.cpp)

target_link_libraries(rm2fb_client
Expand Down
55 changes: 30 additions & 25 deletions libs/rm2fb/Client.cpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
#include "Client.h"

#include "IOCTL.h"
#include "ImageHook.h"

#include "ControlSocket.h"
#include "IOCTL.h"
#include "SharedBuffer.h"
#include "Versions/Version.h"

#include "frida-gum.h"

#include <dlfcn.h>

#include <cstring>
#include <iostream>
#include <unistd.h>

namespace {

ControlSocket clientSock;
bool inXochitl = false;

const unistdpp::Result<ControlSocket>&
getControlSocket() {
static auto socket = []() -> unistdpp::Result<ControlSocket> {
ControlSocket res;
TRY(res.init(nullptr));
TRY(res.connect(default_sock_addr.data()));
return res;
}();

return socket;
}

int
setupHooks() {
const auto* addrs = getAddresses();
if (!addrs) {
if (addrs == nullptr) {
return EXIT_FAILURE;
}

Expand All @@ -36,8 +45,10 @@ setupHooks() {

bool
sendUpdate(const UpdateParams& params) {
const auto& clientSock = unistdpp::fatalOnError(getControlSocket());

return clientSock.sendto(params)
.and_then([](auto _) {
.and_then([&](auto _) {
return clientSock.recvfrom<bool>().map(
[](auto pair) { return pair.first; });
})
Expand All @@ -49,7 +60,8 @@ extern "C" {
int
open64(const char* pathname, int flags, mode_t mode = 0) {
if (!inXochitl && pathname == std::string("/dev/fb0")) {
return fb.fd;
const auto& fb = unistdpp::fatalOnError(SharedFB::getInstance());
return fb.fd.fd;
}

static const auto func_open =
Expand All @@ -61,7 +73,8 @@ open64(const char* pathname, int flags, mode_t mode = 0) {
int
open(const char* pathname, int flags, mode_t mode = 0) {
if (!inXochitl && pathname == std::string("/dev/fb0")) {
return fb.fd;
const auto& fb = unistdpp::fatalOnError(SharedFB::getInstance());
return fb.fd.fd;
}

static const auto func_open =
Expand All @@ -72,7 +85,8 @@ open(const char* pathname, int flags, mode_t mode = 0) {

int
close(int fd) {
if (fd == fb.fd) {
if (const auto& fb = SharedFB::getInstance();
fb.has_value() && fd == fb->fd.fd) {
return 0;
}

Expand All @@ -82,7 +96,8 @@ close(int fd) {

int
ioctl(int fd, unsigned long request, char* ptr) {
if (!inXochitl && fd == fb.fd) {
if (const auto& fb = SharedFB::getInstance();
!inXochitl && fb.has_value() && fd == fb->fd.fd) {
return handleIOCTL(request, ptr);
}

Expand Down Expand Up @@ -119,25 +134,15 @@ __libc_start_main(int (*_main)(int, char**, char**),
setenv("RM2FB_SHIM", "1", true);
setenv("RM2STUFF_RM2FB", "1", true);

if (fb.mem == nullptr) {
std::cout << "No rm2fb shared memory\n";
return EXIT_FAILURE;
}

if (!clientSock.init(nullptr)) {
std::cout << "No rm2fb socket\n";
return EXIT_FAILURE;
}
if (!clientSock.connect(default_sock_addr.data())) {
std::cout << "No rm2fb socket\n";
return EXIT_FAILURE;
}

char pathBuffer[PATH_MAX];
auto size = readlink("/proc/self/exe", pathBuffer, PATH_MAX);

if (std::string_view(pathBuffer, size) == "/usr/bin/xochitl") {
inXochitl = true;

unistdpp::fatalOnError(SharedFB::getInstance(), "Error making shared FB");
unistdpp::fatalOnError(getControlSocket(), "Error creating control socket");

if (setupHooks() != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
Expand Down
5 changes: 3 additions & 2 deletions libs/rm2fb/ControlSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ struct ControlSocket {

template<typename T,
typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
[[nodiscard]] unistdpp::Result<std::pair<T, unistdpp::Address>> recvfrom() {
[[nodiscard]] unistdpp::Result<std::pair<T, unistdpp::Address>> recvfrom()
const {
T t{};
unistdpp::Address addr;
return unistdpp::recvfrom(sock, &t, sizeof(T), 0, &addr).map([&](auto _) {
Expand All @@ -28,7 +29,7 @@ struct ControlSocket {
typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
[[nodiscard]] unistdpp::Result<ssize_t> sendto(
const T& t,
std::optional<unistdpp::Address> dest = std::nullopt) {
std::optional<unistdpp::Address> dest = std::nullopt) const {
return unistdpp::sendto(
sock, &t, sizeof(T), 0, dest.has_value() ? &*dest : nullptr);
}
Expand Down
11 changes: 5 additions & 6 deletions libs/rm2fb/ImageHook.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#include "ImageHook.h"
#include "SharedBuffer.h"

#include <dlfcn.h>
#include <iostream>

SharedFB fb(default_fb_name);

extern "C" {

void
Expand All @@ -17,12 +15,13 @@ _ZN6QImageC1EiiNS_6FormatE(void* that, int x, int y, int f) {
void*, uint8_t*, int32_t, int32_t, int32_t, int, void (*)(void*), void*))
dlsym(RTLD_NEXT, "_ZN6QImageC1EPhiiiNS_6FormatEPFvPvES2_");

if (x == fb_width && y == fb_height && first_alloc && fb.mem != nullptr) {
if (const auto& fb = SharedFB::getInstance();
x == fb_width && y == fb_height && first_alloc && fb.has_value()) {
std::cerr << "REPLACING THE IMAGE with shared memory\n";

first_alloc = false;

qImageCtorWithBuffer(that,
reinterpret_cast<uint8_t*>(fb.mem),
reinterpret_cast<uint8_t*>(fb->mem.get()),
fb_width,
fb_height,
fb_width * fb_pixel_size,
Expand Down
5 changes: 0 additions & 5 deletions libs/rm2fb/ImageHook.h

This file was deleted.

19 changes: 10 additions & 9 deletions libs/rm2fb/Server.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "ControlSocket.h"
#include "ImageHook.h"
#include "InputDevice.h"
#include "Message.h"
#include "SharedBuffer.h"
#include "Versions/Version.h"

#include <unistdpp/file.h>
Expand Down Expand Up @@ -129,7 +129,7 @@ getTcpSocket(int port) {
}

bool
doTCPUpdate(unistdpp::FD& fd, const UpdateParams& params) {
doTCPUpdate(unistdpp::FD& fd, const SharedFB& fb, const UpdateParams& params) {
if (auto res = fd.writeAll(params); !res) {
std::cerr << "Error writing: " << to_string(res.error()) << "\n";
fd.close();
Expand All @@ -145,7 +145,8 @@ doTCPUpdate(unistdpp::FD& fd, const UpdateParams& params) {
int fbRow = row + params.y1;

memcpy(&buffer[row * width],
fb.mem + fbRow * fb_width + params.x1, // NOLINT
// NOLINTNEXTLINE
static_cast<uint16_t*>(fb.mem.get()) + fbRow * fb_width + params.x1,
width * sizeof(uint16_t));
}

Expand Down Expand Up @@ -227,9 +228,8 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT
}

// Check shared memory
if (fb.mem == nullptr) {
return EXIT_FAILURE;
}
const auto& fb =
fatalOnError(SharedFB::getInstance(), "Error creating shared FB");

// Call the get or create Instance function.
if (!inQemu) {
Expand All @@ -241,9 +241,9 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT
// The init threads does a memset to 0xff. But if we're activated by a
// systemd socket the shared memory already has some content. So make a
// backup and preserve it.
memcpy(copyBuffer.get(), fb.mem, fb_size);
memcpy(copyBuffer.get(), fb.mem.get(), fb_size);
addrs->initThreads();
memcpy(fb.mem, copyBuffer.get(), fb_size);
memcpy(fb.mem.get(), copyBuffer.get(), fb_size);

std::cout << "SWTCON initalized!\n";
} else {
Expand Down Expand Up @@ -283,7 +283,7 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT
res = addrs->doUpdate(msg);
}
for (auto& client : tcpClients) {
doTCPUpdate(client, msg);
doTCPUpdate(client, fb, msg);
}

// Don't log Stroke updates, unless debug mode is on.
Expand Down Expand Up @@ -321,6 +321,7 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT
.map([&](const auto& msg) {
if (std::holds_alternative<GetUpdate>(msg)) {
doTCPUpdate(tcpClients.back(),
fb,
{ .y1 = 0,
.x1 = 0,
.y2 = fb_height - 1,
Expand Down
60 changes: 27 additions & 33 deletions libs/rm2fb/SharedBuffer.cpp
Original file line number Diff line number Diff line change
@@ -1,56 +1,50 @@
#include "SharedBuffer.h"

#include <cerrno>
#include <cstdio>
#include <unistdpp/file.h>
#include <unistdpp/shared_mem.h>

#include <cstring>
#include <fcntl.h> /* For O_* constants */
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <unistd.h>

SharedFB::SharedFB(const char* path) : fd(shm_open(path, O_RDWR, 0755)) {
using namespace unistdpp;

namespace {
constexpr mode_t shm_mode = 0755;
}

Result<SharedFB>
SharedFB::open(const char* path) {
auto fd = unistdpp::shm_open(path, O_RDWR, shm_mode);

bool clear = false;
if (fd == -1 && errno == ENOENT) {
fd = shm_open(path, O_RDWR | O_CREAT, 0755);
if (!fd.has_value() && fd.error() == std::errc::no_such_file_or_directory) {
fd = unistdpp::shm_open(path, O_RDWR | O_CREAT, shm_mode);
clear = true;
}

if (fd == -1 && errno == EACCES) {
fd = shm_open(path, O_RDWR | O_CREAT, 0755);
if (!fd.has_value() && fd.error() == std::errc::permission_denied) {
fd = unistdpp::shm_open(path, O_RDWR | O_CREAT, shm_mode);
}

if (fd < 0) {
perror("Can't open shm");
return;
if (!fd.has_value()) {
return tl::unexpected(fd.error());
}

ftruncate(fd, fb_size);
mem = (uint16_t*)mmap(nullptr, fb_size, PROT_WRITE, MAP_SHARED, fd, 0);
TRY(unistdpp::ftruncate(*fd, fb_size));
auto mem =
TRY(unistdpp::mmap(nullptr, fb_size, PROT_WRITE, MAP_SHARED, *fd, 0));
if (clear) {
memset(mem, UINT8_MAX, fb_size);
}
}

SharedFB::~SharedFB() {
if (mem != nullptr) {
munmap(mem, fb_size);
memset(mem.get(), UINT8_MAX, fb_size);
}
}

SharedFB::SharedFB(SharedFB&& other) noexcept : fd(other.fd), mem(other.mem) {
other.fd = -1;
other.mem = nullptr;
return SharedFB{ .fd = std::move(*fd), .mem = std::move(mem) };
}

SharedFB&
SharedFB::operator=(SharedFB&& other) noexcept {
// TODO: release
this->fd = other.fd;
this->mem = other.mem;

other.fd = -1;
other.mem = nullptr;

return *this;
const Result<SharedFB>&
SharedFB::getInstance() {
static auto instance = SharedFB::open(default_fb_name);
return instance;
}
17 changes: 7 additions & 10 deletions libs/rm2fb/SharedBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@

#include <cstdint>

#include <unistdpp/mmap.h>
#include <unistdpp/unistdpp.h>

constexpr int fb_width = 1404;
constexpr int fb_height = 1872;
constexpr int fb_pixel_size = sizeof(uint16_t);
constexpr int fb_size = fb_width * fb_height * fb_pixel_size;

constexpr auto default_fb_name = "/rm2fb.01";

// TODO: use unistdpp
struct SharedFB {
int fd = -1;
uint16_t* mem = nullptr;

SharedFB(const char* path);
~SharedFB();
unistdpp::FD fd;
unistdpp::MmapPtr mem;

SharedFB(const SharedFB& other) = delete;
SharedFB& operator=(const SharedFB& other) = delete;
static unistdpp::Result<SharedFB> open(const char* path);

SharedFB(SharedFB&& other) noexcept;
SharedFB& operator=(SharedFB&& other) noexcept;
static const unistdpp::Result<SharedFB>& getInstance();
};
Loading

0 comments on commit edc022d

Please sign in to comment.