This repository has been archived by the owner on Jan 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Andrew Strelsky
committed
Sep 10, 2023
1 parent
1d29f51
commit e7dddd0
Showing
9 changed files
with
615 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <pthread.h> | ||
#include <sys/_stdint.h> | ||
#include <sys/types.h> | ||
#include "msg.hpp" | ||
#include "thread.hpp" | ||
#include "util.hpp" | ||
|
||
extern "C" void sceLncUtilGetAppTitleId(uint32_t appId, char *titleId); | ||
|
||
class LaunchListeners { | ||
|
||
// I should have made this a set | ||
// realistically these will be small though | ||
Vector<uint32_t> appIds{}; | ||
mutable Mutex mtx{}; | ||
|
||
public: | ||
void append(const uint32_t appId) noexcept { | ||
auto lock = mtx.lock(); | ||
for (const auto id :appIds) { | ||
if (id == appId) { | ||
return; | ||
} | ||
} | ||
appIds.push_back(appId); | ||
} | ||
|
||
void remove(const uint32_t appId) noexcept { | ||
auto lock = mtx.lock(); | ||
for (const auto &id :appIds) { | ||
if (id == appId) { | ||
appIds.erase(&id); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
void handle(const pid_t pid) noexcept { | ||
auto lock = mtx.lock(); | ||
size_t length = appIds.size(); | ||
for (int i = 0; i < length; i++) { | ||
const auto &id = appIds[i]; | ||
if (sceAppMessagingSendMsg(id, BREW_MSG_TYPE_APP_LAUNCHED, &pid, sizeof(pid), 0) != 0) { | ||
i--; | ||
length--; | ||
appIds.erase(&id); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
struct RegisteredPrefix { | ||
uint32_t appId; | ||
uint32_t prefix; | ||
}; | ||
|
||
class PrefixHandlers { | ||
|
||
Vector<RegisteredPrefix> ids{}; | ||
mutable Mutex mtx{}; | ||
|
||
public: | ||
void append(uint32_t appId, uint32_t prefix) noexcept { | ||
auto lock = mtx.lock(); | ||
for (const auto &id : ids) { | ||
constexpr auto TITLEID_SIZE = 9; | ||
char titleId[TITLEID_SIZE + 1]{}; | ||
if (id.prefix == prefix) { | ||
sceLncUtilGetAppTitleId(appId, titleId); | ||
char sPrefix[sizeof(prefix) + 1]; | ||
*reinterpret_cast<uint32_t *>(sPrefix) = prefix; | ||
sPrefix[sizeof(sPrefix) - 1] = '\0'; | ||
printf("%s already registered to handle prefix %s\n", titleId, sPrefix); | ||
return; | ||
} | ||
} | ||
ids.emplace_back(appId, prefix); | ||
} | ||
|
||
bool handle(const uint32_t prefix, const pid_t pid) noexcept { | ||
auto lock = mtx.lock(); | ||
size_t length = ids.size(); | ||
for (int i = 0; i < length; i++) { | ||
const auto &id = ids[i]; | ||
if (id.prefix == prefix) { | ||
if (sceAppMessagingSendMsg(id.appId, BREW_MSG_TYPE_APP_LAUNCHED, &pid, sizeof(pid), 0) != 0) { | ||
i--; | ||
length--; | ||
ids.erase(&id); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
bool canHandle(const uint32_t prefix) const noexcept { | ||
auto lock = mtx.lock(); | ||
for (const auto &id : ids) { | ||
if (id.prefix == prefix) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
}; | ||
|
||
static PrefixHandlers prefixHandlers{}; // NOLINT | ||
static LaunchListeners launchListeners{}; // NOLINT | ||
|
||
static int messageThread(void *unused) noexcept { | ||
(void)unused; | ||
static AppMessage msg{}; | ||
|
||
while (true) { | ||
if (sceAppMessagingReceiveMsg(&msg) < 0) { | ||
puts("sceAppMessagingReceiveMsg failed"); | ||
} | ||
printf("received msg from 0x%04x\n", msg.sender); | ||
printf("msgType: 0x%x\n", msg.msgType); | ||
printf("payloadSize: 0x%x\n", msg.payloadSize); | ||
switch (msg.msgType) { | ||
case BREW_MSG_TYPE_REGISTER_PREFIX_HANDLER: { | ||
prefixHandlers.append(msg.sender, *reinterpret_cast<uint32_t *>(msg.payload)); | ||
break; | ||
} | ||
case BREW_MSG_TYPE_REGISTER_LAUNCH_LISTENER: | ||
if (*msg.payload) { | ||
launchListeners.append(msg.sender); | ||
} else { | ||
launchListeners.remove(msg.sender); | ||
} | ||
break; | ||
default: | ||
puts("unexpected msgType"); | ||
break; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
JThread startMessageReceiver() noexcept { | ||
return JThread{messageThread}; | ||
} | ||
|
||
bool notifyHandlers(const uint32_t prefix, const pid_t pid, const bool isHomebrew) noexcept { | ||
if (isHomebrew) { | ||
// prefix handlers are notified first since they are responsible for loading the elf if applicable | ||
// listeners need not be notified | ||
return prefixHandlers.handle(prefix, pid); | ||
} | ||
launchListeners.handle(pid); | ||
return false; | ||
} | ||
|
||
bool hasPrefixHandler(const uint32_t prefix) noexcept { | ||
return prefixHandlers.canHandle(prefix); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#include <stdint.h> | ||
#include <stdlib.h> | ||
#include "thread.hpp" | ||
|
||
struct AppMessage; | ||
|
||
extern "C" uint32_t sceAppMessagingSendMsg(uint32_t appId, uint32_t msgType, const void *msg, size_t msgLength, uint32_t flags); | ||
|
||
extern "C" int sceAppMessagingReceiveMsg(const AppMessage *msg); | ||
|
||
struct AppMessage { | ||
static constexpr size_t PAYLOAD_SIZE = 8192; | ||
uint32_t sender; | ||
uint32_t msgType; | ||
uint8_t payload[PAYLOAD_SIZE]; | ||
uint32_t payloadSize; | ||
uint64_t timestamp; | ||
}; | ||
|
||
enum HomebrewDaemonMessageType : uint32_t { | ||
BREW_MSG_TYPE_REGISTER_PREFIX_HANDLER = 0x1000000, | ||
BREW_MSG_TYPE_REGISTER_LAUNCH_LISTENER, | ||
BREW_MSG_TYPE_APP_LAUNCHED | ||
}; | ||
|
||
JThread startMessageReceiver() noexcept; | ||
bool notifyHandlers(const uint32_t prefix, const pid_t pid, const bool isHomebrew) noexcept; | ||
bool hasPrefixHandler(const uint32_t prefix) noexcept; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.