diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..152a33b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "plugin/ArticProtocol"] + path = plugin/ArticProtocol + url = https://github.com/PabloMK7/ArticProtocol.git diff --git a/plugin/ArticProtocol b/plugin/ArticProtocol new file mode 160000 index 0000000..09750e6 --- /dev/null +++ b/plugin/ArticProtocol @@ -0,0 +1 @@ +Subproject commit 09750e64c81fa2c6fbcebeb3e0059790c47c0eb3 diff --git a/plugin/Makefile b/plugin/Makefile index ca6781f..8144228 100644 --- a/plugin/Makefile +++ b/plugin/Makefile @@ -11,8 +11,8 @@ TARGET := ArticBase PLGINFO := build/ArticBase.plgInfo BUILD := build -INCLUDES := includes -SOURCES := sources sources/CTRPluginFramework +INCLUDES := ArticProtocol/includes includes +SOURCES := ArticProtocol/sources sources sources/CTRPluginFramework VERSION_MAJOR := 1 VERSION_MINOR := 2 diff --git a/plugin/includes/ArticBaseCommon.hpp b/plugin/includes/ArticBaseCommon.hpp deleted file mode 100644 index fc11e45..0000000 --- a/plugin/includes/ArticBaseCommon.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -#include <3ds/types.h> -#include - -namespace ArticBaseCommon { - enum class MethodState : int { - PARSING_INPUT = 0, - PARAMETER_TYPE_MISMATCH = 1, - PARAMETER_COUNT_MISMATCH = 2, - BIG_BUFFER_READ_FAIL = 3, - BIG_BUFFER_WRITE_FAIL = 4, - OUT_OF_MEMORY = 5, - - GENERATING_OUTPUT = 6, - UNEXPECTED_PARSING_INPUT = 7, - OUT_OF_MEMORY_OUTPUT = 8, - - INTERNAL_METHOD_ERROR = 9, - FINISHED = 10, - }; - enum class RequestParameterType : u16 { - IN_INTEGER_8 = 0, - IN_INTEGER_16 = 1, - IN_INTEGER_32 = 2, - IN_INTEGER_64 = 3, - IN_SMALL_BUFFER = 4, - IN_BIG_BUFFER = 5, - }; - struct RequestParameter { - RequestParameterType type; - union { - u16 parameterSize; - u16 bigBufferID; - }; - - char data[0x1C]; - }; - struct RequestPacket { - u32 requestID; - std::array method; - u32 parameterCount; - }; - static_assert(sizeof(RequestPacket) == 0x28); - - struct Buffer { - u32 bufferID; - u32 bufferSize; - - char data[]; - }; - - struct ResponseMethod { - enum class ArticResult : u32 { - SUCCESS = 0, - METHOD_NOT_FOUND = 1, - METHOD_ERROR = 2, - PROVIDE_INPUT = 3, - }; - ArticResult articResult{}; - union { - int methodResult{}; - int provideInputBufferID; - }; - int bufferSize{}; - u8 padding[0x10]{}; - }; - - struct DataPacket { - DataPacket() {} - u32 requestID{}; - - union { - char dataRaw[0x1C]{}; - ResponseMethod resp; - }; - }; - - static_assert(sizeof(DataPacket) == 0x20); -}; - diff --git a/plugin/includes/ArticBaseFunctions.hpp b/plugin/includes/ArticBaseFunctions.hpp deleted file mode 100644 index 91911e8..0000000 --- a/plugin/includes/ArticBaseFunctions.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "3ds.h" -#include "map" -#include "ArticBaseCommon.hpp" -#include "ArticBaseServer.hpp" -#include "memory.h" -#include "string" - -namespace ArticBaseFunctions { - extern std::map functionHandlers; - extern std::vector setupFunctions; - extern std::vector destructFunctions; - - enum class HandleType { - FILE, - DIR, - ARCHIVE - }; - - // Controller_Start - namespace ArticController { - extern Thread thread; - extern bool thread_run; - extern int socket_fd; - extern volatile bool socket_ready; - void Handler(void* arg); - }; -}; \ No newline at end of file diff --git a/plugin/includes/ArticBaseServer.hpp b/plugin/includes/ArticBaseServer.hpp deleted file mode 100644 index f9cd136..0000000 --- a/plugin/includes/ArticBaseServer.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#pragma once -#include "Main.hpp" -#include "ArticBaseCommon.hpp" -#include "queue" -#include -#include "CTRPluginFramework/CTRPluginFramework.hpp" - -class ArticBaseServer { -public: - ArticBaseServer(int socket_fd); - ~ArticBaseServer(); - - void Serve(); - void QueryStop(); - - static bool SetNonBlock(int sockFD, bool nonBlocking); - static bool Read(int& sockFD, void* buffer, size_t size); - static bool Write(int& sockFD, void* buffer, size_t size); - static size_t RecvFrom(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size); - static size_t SendTo(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size); -private: - void Stop(); - static constexpr size_t MAX_WORK_BUF_SIZE = 4 * 1024 * 1024 + 512 * 1024; // 4.5MB - static constexpr size_t MAX_PARAM_AMOUNT = 10; - - class RequestHandler { - public: - RequestHandler(ArticBaseServer* serv, int id); - ~RequestHandler(); - ArticBaseServer* server; - Thread thread; - static void HandleThread(void* arg); - void Serve(); - bool ready = false; - bool run = true; - int workBufferSize; - void* workBuffer; - int id; - int listen_fd = -1; - int accept_fd = -1; - }; - - class Request { - public: - ArticBaseCommon::RequestPacket reqPacket; - std::vector reqParameters; - }; - - static constexpr const char* VERSION = "2"; - - int socketFd; - bool run = true; - bool stopQueried = false; - - std::queue pendingRequests; - CTRPluginFramework::Mutex pendingRequestsMutex; - LightEvent newPendingRequest; - std::array requestHandlers; - -public: - class MethodInterface { - public: - using MethodState = ArticBaseCommon::MethodState; - - MethodInterface(Request& _req, void* _workBuffer, size_t _workBufferSize, int& _socketFD) : req(_req), workBuffer(_workBuffer, _workBufferSize), socketFD(_socketFD) {}; - - bool GetParameterS8(s8& out); - bool GetParameterS16(s16& out); - bool GetParameterS32(s32& out); - bool GetParameterS64(s64& out); - bool GetParameterBuffer(void*& outBuff, size_t& outSize); - - bool FinishInputParameters() { - if (state != MethodState::PARSING_INPUT) - return false; - if (currParameter != req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - state = MethodState::GENERATING_OUTPUT; - workBuffer.Clear(); - return true; - } - - ArticBaseCommon::Buffer* ReserveResultBuffer(u32 bufferID, size_t resultBuffSize); - ArticBaseCommon::Buffer* ResizeLastResultBuffer(ArticBaseCommon::Buffer* buffer, size_t newSize); - - void FinishGood(int returnValue); - void FinishInternalError(); - - int GetMethodReturnValue() { - return returnValue; - } - MethodState GetMethodState() { - return state; - } - - private: - class WorkBufferHandler - { - private: - void* workBuffer; - size_t workBufferSize; - size_t offset = 0; - public: - WorkBufferHandler(void* _workBuffer, size_t _workBufferSize) : workBuffer(_workBuffer), workBufferSize(_workBufferSize) {} - - void Clear() { - offset = 0; - } - - size_t Capacity() { - return workBufferSize; - } - - size_t Size() { - return offset; - } - - ArticBaseCommon::Buffer* Reserve(u32 bufferID, u32 bufferSize) { - if (offset + sizeof(ArticBaseCommon::Buffer) + bufferSize > workBufferSize) { - logger.Error("o=0x%08X, bs=0x%08X, wbs=0x%08X", offset, bufferSize, workBufferSize); - return nullptr; - } - ArticBaseCommon::Buffer* buf = (ArticBaseCommon::Buffer*)((uintptr_t)workBuffer + offset); - offset += sizeof(ArticBaseCommon::Buffer) + bufferSize; - buf->bufferID = bufferID; - buf->bufferSize = bufferSize; - return buf; - } - - enum class ResizeState { - GOOD, - INPUT_ERROR, - OUT_OF_MEMORY, - }; - ResizeState ResizeLast(ArticBaseCommon::Buffer* buffer, size_t newSize); - - std::pair GetRaw() { - return std::make_pair(workBuffer, Size()); - } - }; - - friend class RequestHandler; - std::pair GetOutputBuffer() { - return workBuffer.GetRaw(); - } - Request& req; - int& socketFD; - WorkBufferHandler workBuffer; - int currParameter = 0; - MethodState state = MethodState::PARSING_INPUT; - int returnValue = 0; - }; -}; \ No newline at end of file diff --git a/plugin/includes/Logger.hpp b/plugin/includes/Logger.hpp deleted file mode 100644 index ca82c9c..0000000 --- a/plugin/includes/Logger.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include "3ds.h" -#include "string" -#include "queue" -#include "CTRPluginFramework/System/Mutex.hpp" -#include "CTRPluginFramework/System/Lock.hpp" - -class Logger { -public: - Logger(); - void Start(); - void End(); - ~Logger(); - void Raw(bool isTopScr, const char* fmt, ...); - void Info(const char* fmt, ...); - void Debug(const char* fmt, ...); - void Warning(const char* fmt, ...); - void Error(const char* fmt, ...); - void Traffic(const char* fmt, ...); - - void Wait(); - - bool debug_enable = false; -private: - struct PendingLog { - enum class Type : u8 { - RAW, - DEBUG, - INFO, - WARNING, - ERROR, - TRAFFIC, - }; - Type type; - bool isTopScr = true; - std::string string; - }; - static void LoggerThread(void* arg); - void Handler(); - Thread thread; - LightEvent event; - - std::queue pendingLogs; - CTRPluginFramework::Mutex pendingLogsMutex; - - bool run = true; -}; \ No newline at end of file diff --git a/plugin/sources/ArticBaseServer.cpp b/plugin/sources/ArticBaseServer.cpp deleted file mode 100644 index a9a89d2..0000000 --- a/plugin/sources/ArticBaseServer.cpp +++ /dev/null @@ -1,638 +0,0 @@ -#include "ArticBaseServer.hpp" -#include "ArticBaseFunctions.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern int transferedBytes; - -ArticBaseServer::ArticBaseServer(int sock_fd) { - socketFd = sock_fd; - - LightEvent_Init(&newPendingRequest, ResetType::RESET_ONESHOT); - - for (int i = 0; i < requestHandlers.size(); i++) { - requestHandlers[i] = new RequestHandler(this, i); - } -} - -ArticBaseServer::~ArticBaseServer() { - for (int i = 0; i < requestHandlers.size(); i++) { - delete requestHandlers[i]; - } - if (socketFd >= 0) { - int fd = socketFd; - socketFd = -1; - shutdown(fd, SHUT_RDWR); - close(fd); - } -} - -void ArticBaseServer::Serve() { - ArticBaseCommon::RequestPacket req; - std::array params; - int retryCount = 0; - while (run && !stopQueried) { - if (!Read(socketFd, &req, sizeof(req))) { - if (stopQueried) { - break; - } - if (run) { - logger.Error("Server: Error reading from socket"); - svcSleepThread(1000000000); - if (++retryCount == 3) { - break; - } - } - continue; - } - - std::array methodArray = {0}; - memcpy(methodArray.data(), req.method.data(), req.method.size()); - // Process special method now, delegate otherwise - if (methodArray[0] == '$') { - logger.Debug("Server: Processing %s (rID %d)", methodArray.data(), req.requestID); - ArticBaseCommon::DataPacket resp{}; - resp.requestID = req.requestID; - std::string_view method(methodArray.data()); - if (method == "$PING") { - // Do nothing - } else if (method == "$VERSION") { - strcpy(resp.dataRaw, VERSION); - } else if (method == "$PORTS") { - snprintf(resp.dataRaw, sizeof(resp.dataRaw), "%d,%d,%d,%d", SERVER_PORT + 1, SERVER_PORT + 2, SERVER_PORT + 3, SERVER_PORT + 4); - } else if (method == "$MAXSIZE") { - snprintf(resp.dataRaw, sizeof(resp.dataRaw), "%d", ArticBaseServer::MAX_WORK_BUF_SIZE); - } else if (method == "$MAXPARAM") { - snprintf(resp.dataRaw, sizeof(resp.dataRaw), "%d", ArticBaseServer::MAX_PARAM_AMOUNT); - } else if (method == "$READY") { - bool ready = true; - for (int i = 0; i < requestHandlers.size(); i++) { - if (!requestHandlers[i]->ready) { - ready = false; - } - } - snprintf(resp.dataRaw, sizeof(resp.dataRaw), "%d", ready ? 1 : 0); - } else if (method == "$STOP") { - stopQueried = true; - } else { - logger.Error("Server: Method not found: %s", methodArray.data()); - } - if (!Write(socketFd, &resp, sizeof(resp))) { - if (run) logger.Error("Server: Error writing to socket"); - continue; - } - } else { - u32 readParams = 0; - if (req.parameterCount) { - if (req.parameterCount <= MAX_PARAM_AMOUNT) { - if (!Read(socketFd, params.data(), req.parameterCount * sizeof(ArticBaseCommon::RequestParameter))) { - if (run) logger.Error("Server: Error reading from socket"); - continue; - } - readParams = req.parameterCount; - } else { - logger.Error("Server: Too many parameters in request"); - readParams = 0; - } - } - - { - CTRPluginFramework::Lock l(pendingRequestsMutex); - pendingRequests.push(Request{.reqPacket = req, .reqParameters = std::vector(params.begin(), params.begin() + readParams)}); - } - LightEvent_Signal(&newPendingRequest); - } - } - Stop(); -} - -void ArticBaseServer::QueryStop() { - stopQueried = true; - if (socketFd >= 0) { - int fd = socketFd; - socketFd = -1; - shutdown(fd, SHUT_RDWR); - close(fd); - } -} - -bool ArticBaseServer::SetNonBlock(int sockFD, bool nonBlocking) { - int flags = fcntl(sockFD, F_GETFL, 0); - if (flags < 0) { - return false; - } - if (nonBlocking) { - flags |= O_NONBLOCK; - } else { - flags &= ~O_NONBLOCK; - } - int res = fcntl(sockFD, F_SETFL, flags); - if (res < 0) { - return false; - } - return true; -} - - -void ArticBaseServer::Stop() { - if (!run) - return; - run = false; - if (socketFd >= 0) { - int fd = socketFd; - socketFd = -1; - shutdown(fd, SHUT_RDWR); - close(fd); - } - for (int i = 0; i < requestHandlers.size(); i++) { - RequestHandler& handler = *requestHandlers[i]; - handler.run = false; - if (handler.accept_fd >= 0) { - int fd = handler.accept_fd; - handler.accept_fd = -1; - shutdown(fd, SHUT_RDWR); - close(fd); - } - if (handler.listen_fd >= 0) { - int fd = handler.listen_fd; - handler.listen_fd = -1; - shutdown(fd, SHUT_RDWR); - close(fd); - } - } - while(true) { - bool allStopped = true; - for (int i = 0; i < requestHandlers.size(); i++) { - allStopped = allStopped && threadGetExitCode(requestHandlers[i]->thread) == 1; - } - if (allStopped) - break; - svcSleepThread(1000000); - LightEvent_Signal(&newPendingRequest); - } -} - -bool ArticBaseServer::Read(int& sockFD, void* buffer, size_t size) { - size_t read_bytes = 0; - while (read_bytes != size) { - int new_read = recv(sockFD, (void*)((uintptr_t)buffer + read_bytes), size - read_bytes, 0); - if (new_read < 0) { - if (errno == EWOULDBLOCK) { - svcSleepThread(1000000); - continue; - } - read_bytes = 0; - break; - } - transferedBytes += new_read; - read_bytes += new_read; - } - return read_bytes == size; -} - -bool ArticBaseServer::Write(int& sockFD, void* buffer, size_t size) { - size_t write_bytes = 0; - while (write_bytes != size) - { - int new_written = send(sockFD, (void*)((uintptr_t)buffer + write_bytes), size - write_bytes, 0); - if (new_written < 0) { - if (errno == EWOULDBLOCK) { - svcSleepThread(1000000); - continue; - } - write_bytes = 0; - break; - } - transferedBytes += new_written; - write_bytes += new_written; - } - return write_bytes == size; -} - -size_t ArticBaseServer::RecvFrom(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size) { - while (true) { - int new_read = recvfrom(sockFD, buffer, size, 0, (sockaddr*)addr, (socklen_t*)addr_size); - if (new_read < 0) { - if (errno == EWOULDBLOCK) { - svcSleepThread(1000000); - continue; - } - return 0; - } - transferedBytes += new_read; - return new_read; - } -} - -size_t ArticBaseServer::SendTo(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size) { - socklen_t addr_len = *(socklen_t*)addr_size; - while (true) { - int new_written = sendto(sockFD, buffer, size, 0, (sockaddr*)addr, addr_len); - if (new_written < 0) { - if (errno == EWOULDBLOCK) { - svcSleepThread(1000000); - continue; - } - return 0; - } - transferedBytes += new_written; - return new_written; - } -} - -ArticBaseServer::RequestHandler::RequestHandler(ArticBaseServer* serv, int id) { - server = serv; - this->id = id; - - workBufferSize = ArticBaseServer::MAX_WORK_BUF_SIZE; - workBuffer = linearAlloc(workBufferSize); - - if (workBuffer == nullptr) { - logger.Error("Worker %d: Failed to allocate work buffer", id); - } - - s32 prio = 0; - svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); - thread = threadCreate(RequestHandler::HandleThread, this, 0x1000, prio - 1, -2, false); -} - -ArticBaseServer::RequestHandler::~RequestHandler() { - threadJoin(thread, U64_MAX); - threadFree(thread); - - linearFree(workBuffer); -} - -void ArticBaseServer::RequestHandler::HandleThread(void* arg) { - RequestHandler* own = (RequestHandler*)arg; - own->Serve(); - if (own->accept_fd >= 0) { - int fd = own->accept_fd; - shutdown(fd, SHUT_RDWR); - close(fd); - } - logger.Debug("Worker %d: Exited", own->id); - threadExit(1); -} - -void ArticBaseServer::RequestHandler::Serve() { - if (!workBuffer) { - return; - } - - struct sockaddr_in servaddr = {0}; - int res; - listen_fd = socket(AF_INET, SOCK_STREAM, 0); - if (listen_fd < 0) { - logger.Error("Worker %d: Cannot create socket", id); - return; - } - - if (!ArticBaseServer::SetNonBlock(listen_fd, true)) { - logger.Error("Worker %d: Cannot set non-block", id); - close(listen_fd); - listen_fd = -1; - return; - } - - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(SERVER_PORT + id + 1); - res = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); - if (res < 0) { - logger.Error("Worker %d: Failed to bind() to port %d", id, SERVER_PORT + id + 1); - close(listen_fd); - listen_fd = -1; - return; - } - - res = listen(listen_fd, 1); - if (res < 0) { - if (run) { - logger.Error("Worker %d: Failed to listen()", id); - } - close(listen_fd); - listen_fd = -1; - return; - } - - struct in_addr host_id; - host_id.s_addr = gethostid(); - logger.Debug("Worker %d: Listening on: %s:%d", id, inet_ntoa(host_id), SERVER_PORT + id + 1); - - struct sockaddr_in peeraddr = {0}; - socklen_t peeraddr_len = sizeof(peeraddr); - ready = true; - while (true) { - accept_fd = accept(listen_fd, (struct sockaddr *) &peeraddr, &peeraddr_len); - if (accept_fd < 0 || peeraddr_len == 0) { - if (errno == EWOULDBLOCK && run) { - svcSleepThread(10000000); - continue; - } - if (run) { - logger.Error("Worker %d: Failed to accept()", id); - } - close(listen_fd); - listen_fd = -1; - return; - } - break; - } - close(listen_fd); - listen_fd = -1; - - logger.Debug("Worker %d: Accepted %s:%d", id, inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); - - if (!ArticBaseServer::SetNonBlock(accept_fd, true)) { - logger.Error("Worker %d: Cannot set non-block", id); - shutdown(accept_fd, SHUT_RDWR); - close(accept_fd); - accept_fd = -1; - return; - } - - while (true) { - LightEvent_Wait(&server->newPendingRequest); - if (!run) { - break; - } - Request req; - while (run) { - { - CTRPluginFramework::Lock l(server->pendingRequestsMutex); - if (!server->pendingRequests.size()) - break; - req = server->pendingRequests.front(); - server->pendingRequests.pop(); - } - - ArticBaseCommon::DataPacket respPacket{}; - respPacket.requestID = req.reqPacket.requestID; - - std::array methodArray = {0}; - memcpy(methodArray.data(), req.reqPacket.method.data(), req.reqPacket.method.size()); - auto it = ArticBaseFunctions::functionHandlers.find(std::string(methodArray.data())); - if (it == ArticBaseFunctions::functionHandlers.end()) { - respPacket.resp.articResult = ArticBaseCommon::ResponseMethod::ArticResult::METHOD_NOT_FOUND; - logger.Error("Worker %d: Method not found: %s", id, methodArray.data()); - if (!Write(accept_fd, &respPacket, sizeof(respPacket))) { - if (run) - logger.Error("Worker %d: Error writing to socket", id); - return; - } - continue; - } - - logger.Debug("Worker %d: Processing %s (rID %d)", id, methodArray.data(), req.reqPacket.requestID); - MethodInterface mi(req, workBuffer, workBufferSize, accept_fd); - it->second(mi); - - ArticBaseCommon::MethodState mState = mi.GetMethodState(); - if (mState != ArticBaseCommon::MethodState::FINISHED) { - respPacket.resp.articResult = ArticBaseCommon::ResponseMethod::ArticResult::METHOD_ERROR; - logger.Error("Worker %d: %s method error: %d", id, methodArray.data(), mState); - respPacket.resp.methodResult = (int)mState; - if (!Write(accept_fd, &respPacket, sizeof(respPacket))) { - if (run) - logger.Error("Worker %d: Error writing to socket", id); - return; - } - } else { - respPacket.resp.articResult = ArticBaseCommon::ResponseMethod::ArticResult::SUCCESS; - respPacket.resp.methodResult = mi.GetMethodReturnValue(); - auto outBuffer = mi.GetOutputBuffer(); - respPacket.resp.bufferSize = outBuffer.second; - if (!Write(accept_fd, &respPacket, sizeof(respPacket))) { - if (run) - logger.Error("Worker %d: Error writing to socket", id); - return; - } - if (outBuffer.second) - if (!Write(accept_fd, outBuffer.first, outBuffer.second)) { - if (run) - logger.Error("Worker %d: Error writing to socket", id); - return; - } - } - } - } -} - -bool ArticBaseServer::MethodInterface::GetParameterS8(s8& out) { - if (state != MethodState::PARSING_INPUT) - return false; - - if (currParameter >= req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - - ArticBaseCommon::RequestParameter& currParam = req.reqParameters[currParameter++]; - - if (currParam.type == ArticBaseCommon::RequestParameterType::IN_INTEGER_8) { - out = *(s8*)currParam.data; - return true; - } - - state = MethodState::PARAMETER_TYPE_MISMATCH; - return false; -} - -bool ArticBaseServer::MethodInterface::GetParameterS16(s16& out) { - if (state != MethodState::PARSING_INPUT) - return false; - - if (currParameter >= req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - - ArticBaseCommon::RequestParameter& currParam = req.reqParameters[currParameter++]; - - if (currParam.type == ArticBaseCommon::RequestParameterType::IN_INTEGER_16) { - out = *(s16*)currParam.data; - return true; - } - - state = MethodState::PARAMETER_TYPE_MISMATCH; - return false; -} - -bool ArticBaseServer::MethodInterface::GetParameterS32(s32& out) { - if (state != MethodState::PARSING_INPUT) - return false; - - if (currParameter >= req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - - ArticBaseCommon::RequestParameter& currParam = req.reqParameters[currParameter++]; - - if (currParam.type == ArticBaseCommon::RequestParameterType::IN_INTEGER_32) { - out = *(s32*)currParam.data; - return true; - } - - state = MethodState::PARAMETER_TYPE_MISMATCH; - return false; -} - -bool ArticBaseServer::MethodInterface::GetParameterS64(s64& out) { - if (state != MethodState::PARSING_INPUT) - return false; - - if (currParameter >= req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - - ArticBaseCommon::RequestParameter& currParam = req.reqParameters[currParameter++]; - - if (currParam.type == ArticBaseCommon::RequestParameterType::IN_INTEGER_64) { - out = *(s64*)currParam.data; - return true; - } - - state = MethodState::PARAMETER_TYPE_MISMATCH; - return false; -} - -bool ArticBaseServer::MethodInterface::GetParameterBuffer(void*& outBuff, size_t& outSize) { - if (state != MethodState::PARSING_INPUT) - return false; - - if (currParameter >= req.reqPacket.parameterCount) { - state = MethodState::PARAMETER_COUNT_MISMATCH; - return false; - } - - ArticBaseCommon::RequestParameter& currParam = req.reqParameters[currParameter++]; - - if (currParam.type == ArticBaseCommon::RequestParameterType::IN_SMALL_BUFFER) { - outBuff = currParam.data; - outSize = currParam.parameterSize; - return true; - } else if (currParam.type == ArticBaseCommon::RequestParameterType::IN_BIG_BUFFER) { - // Perform request for buffer - size_t bufferSize = *(size_t*)currParam.data; - ArticBaseCommon::Buffer* buf = workBuffer.Reserve(currParam.bigBufferID, bufferSize); - if (buf == nullptr) { - state = MethodState::OUT_OF_MEMORY; - return false; - } - - ArticBaseCommon::DataPacket dataPacket{}; - dataPacket.requestID = req.reqPacket.requestID; - dataPacket.resp.articResult = ArticBaseCommon::ResponseMethod::ArticResult::PROVIDE_INPUT; - dataPacket.resp.provideInputBufferID = currParam.bigBufferID; - dataPacket.resp.bufferSize = (int)bufferSize; - - if (!Write(socketFD, &dataPacket, sizeof(dataPacket))) { - state = MethodState::BIG_BUFFER_WRITE_FAIL; - return false; - } - - if (!Read(socketFD, &dataPacket, sizeof(dataPacket))) { - state = MethodState::BIG_BUFFER_READ_FAIL; - return false; - } - - if (dataPacket.requestID != req.reqPacket.requestID || - dataPacket.resp.articResult != ArticBaseCommon::ResponseMethod::ArticResult::PROVIDE_INPUT || - dataPacket.resp.provideInputBufferID != currParam.bigBufferID || - dataPacket.resp.bufferSize != (int)bufferSize) { - - state = MethodState::BIG_BUFFER_READ_FAIL; - return false; - } - - if (!Read(socketFD, buf->data, buf->bufferSize)) { - state = MethodState::BIG_BUFFER_READ_FAIL; - return false; - } - outBuff = buf->data; - outSize = buf->bufferSize; - return true; - } - state = MethodState::PARAMETER_TYPE_MISMATCH; - return false; -} - -ArticBaseCommon::Buffer* ArticBaseServer::MethodInterface::ReserveResultBuffer(u32 bufferID, size_t resultBuffSize) { - if (state != MethodState::GENERATING_OUTPUT) { - if (state == MethodState::PARSING_INPUT) { - state = MethodState::UNEXPECTED_PARSING_INPUT; - } - return nullptr; - } - - ArticBaseCommon::Buffer* buf = workBuffer.Reserve(bufferID, resultBuffSize); - if (buf == nullptr) { - state = MethodState::OUT_OF_MEMORY_OUTPUT; - return nullptr; - } - return buf; -} - -ArticBaseCommon::Buffer* ArticBaseServer::MethodInterface::ResizeLastResultBuffer(ArticBaseCommon::Buffer* buffer, size_t newSize) { - if (state != MethodState::GENERATING_OUTPUT) { - if (state == MethodState::PARSING_INPUT) { - state = MethodState::UNEXPECTED_PARSING_INPUT; - } - return nullptr; - } - WorkBufferHandler::ResizeState resizeSate = workBuffer.ResizeLast(buffer, newSize); - if (resizeSate != WorkBufferHandler::ResizeState::GOOD) { - if (resizeSate == WorkBufferHandler::ResizeState::OUT_OF_MEMORY) - state = MethodState::OUT_OF_MEMORY_OUTPUT; - else - state = MethodState::INTERNAL_METHOD_ERROR; - return nullptr; - } - return buffer; -} - -void ArticBaseServer::MethodInterface::FinishGood(int returnValue) { - if (state == MethodState::GENERATING_OUTPUT) - state = MethodState::FINISHED; - if (state == MethodState::PARSING_INPUT) - state = MethodState::UNEXPECTED_PARSING_INPUT; - this->returnValue = returnValue; -} -void ArticBaseServer::MethodInterface::FinishInternalError() { - if (state == MethodState::GENERATING_OUTPUT || state == MethodState::PARSING_INPUT) - state = MethodState::INTERNAL_METHOD_ERROR; - return; -} - -ArticBaseServer::MethodInterface::WorkBufferHandler::ResizeState ArticBaseServer::MethodInterface::WorkBufferHandler::ResizeLast(ArticBaseCommon::Buffer* buffer, size_t newSize) { - if (buffer->bufferSize == newSize) - return ResizeState::GOOD; - if ((uintptr_t)workBuffer + offset != (uintptr_t)buffer + buffer->bufferSize + sizeof(ArticBaseCommon::Buffer)) - return ResizeState::INPUT_ERROR; - int sizeDiff = newSize - buffer->bufferSize; - if (newSize == 0) { - // Remove the buffer completely - sizeDiff -= sizeof(ArticBaseCommon::Buffer); - } - if (offset + sizeDiff > workBufferSize) - return ResizeState::OUT_OF_MEMORY; - offset += sizeDiff; - if (newSize != 0) - buffer->bufferSize = newSize; - return ResizeState::GOOD; -} \ No newline at end of file diff --git a/plugin/sources/Logger.cpp b/plugin/sources/Logger.cpp deleted file mode 100644 index b515ac0..0000000 --- a/plugin/sources/Logger.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "Logger.hpp" -#include -#include -#include -#include "3ds.h" - -Logger::Logger() {} - -void Logger::Start() { - LightEvent_Init(&event, ResetType::RESET_ONESHOT); - - s32 prio = 0; - svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); - - thread = threadCreate(LoggerThread, this, 0x300, prio + 1, -2, false); -} - -void Logger::End() { - run = false; - LightEvent_Signal(&event); - threadJoin(thread, U64_MAX); -} - -Logger::~Logger() { - if (run) End(); - threadFree(thread); -} - -extern PrintConsole topScreenConsole, bottomScreenConsole; - -void Logger::Raw(bool isTopScr, const char* fmt, ...) { - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::RAW, .isTopScr = isTopScr, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Info(const char* fmt, ...) { - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::INFO, .isTopScr = true, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Debug(const char* fmt, ...) { - if (!debug_enable) return; - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::DEBUG, .isTopScr = true, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Warning(const char* fmt, ...) { - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::WARNING, .isTopScr = true, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Error(const char* fmt, ...) { - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::ERROR, .isTopScr = true, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Traffic(const char* fmt, ...) { - va_list valist; - char buffer[256]; - va_start(valist, fmt); - int ret = vsnprintf(buffer, 255, fmt, valist); - va_end(valist); - if (ret >= 0) buffer[ret] = '\0'; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - pendingLogs.push(PendingLog{.type = PendingLog::Type::TRAFFIC, .isTopScr = false, .string{buffer}}); - } - LightEvent_Signal(&event); -} - -void Logger::Handler() { - bool currentIsTop = true; - int back; - while (true) { - LightEvent_Wait(&event); - if (!run) { - break; - } - while (run) { - PendingLog log; - { - CTRPluginFramework::Lock l(pendingLogsMutex); - if (!pendingLogs.size()) - break; - log = pendingLogs.front(); - pendingLogs.pop(); - } - if (log.isTopScr && !currentIsTop) { - currentIsTop = true; - consoleSelect(&topScreenConsole); - } - if (!log.isTopScr && currentIsTop) { - currentIsTop = false; - consoleSelect(&bottomScreenConsole); - } - switch (log.type) - { - case PendingLog::Type::RAW: - back = bottomScreenConsole.cursorY; - bottomScreenConsole.cursorY = 0; - printf("%s\n", log.string.c_str()); - bottomScreenConsole.cursorY = back; - break; - case PendingLog::Type::DEBUG: - printf("[D] %s\n", log.string.c_str()); - break; - case PendingLog::Type::INFO: - printf("[I] %s\n", log.string.c_str()); - break; - case PendingLog::Type::WARNING: - topScreenConsole.fg = 19; - printf("[W] %s\n", log.string.c_str()); - topScreenConsole.fg = 0; - break; - case PendingLog::Type::ERROR: - topScreenConsole.fg = 17; - printf("[E] %s\n", log.string.c_str()); - topScreenConsole.fg = 0; - break; - case PendingLog::Type::TRAFFIC: - back = bottomScreenConsole.cursorY; - bottomScreenConsole.cursorY = 25; - printf(log.string.c_str()); - bottomScreenConsole.cursorY = back; - break; - default: - break; - } - } - } -} - -void Logger::LoggerThread(void* arg) { - Logger* l = (Logger*)arg; - l->Handler(); -} \ No newline at end of file