diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index b4555d87e..978d74f65 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -1,8 +1,11 @@ #pragma once -#include "stratosphere/ipc_templating.hpp" #include "stratosphere/iwaitable.hpp" #include "stratosphere/iserviceobject.hpp" +#include "stratosphere/iserver.hpp" #include "stratosphere/servicesession.hpp" #include "stratosphere/serviceserver.hpp" -#include "stratosphere/waitablemanager.hpp" \ No newline at end of file +#include "stratosphere/managedportserver.hpp" +#include "stratosphere/waitablemanager.hpp" + +#include "stratosphere/ipc_templating.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp new file mode 100644 index 000000000..0188000c1 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp @@ -0,0 +1,115 @@ +#pragma once +#include +#include + +#include "iserviceobject.hpp" +#include "iwaitable.hpp" +#include "servicesession.hpp" + +template +class ServiceSession; + +template +class IServer : public IWaitable { + static_assert(std::is_base_of::value, "Service Objects must derive from IServiceObject"); + protected: + Handle port_handle; + unsigned int max_sessions; + unsigned int num_sessions; + ServiceSession **sessions; + virtual Result register_self(const char *service_name) { + return smRegisterService(&this->port_handle, service_name, false, this->max_sessions); + } + + public: + IServer(const char *service_name, unsigned int max_s) : max_sessions(max_s) { + if (R_FAILED(register_self(service_name))) { + /* TODO: Panic. */ + } + this->sessions = new ServiceSession *[this->max_sessions]; + for (unsigned int i = 0; i < this->max_sessions; i++) { + this->sessions[i] = NULL; + } + this->num_sessions = 0; + } + + virtual ~IServer() { + for (unsigned int i = 0; i < this->max_sessions; i++) { + if (this->sessions[i]) { + delete this->sessions[i]; + } + + delete this->sessions; + } + + if (port_handle) { + svcCloseHandle(port_handle); + } + } + + /* IWaitable */ + virtual unsigned int get_num_waitables() { + unsigned int n = 1; + for (unsigned int i = 0; i < this->max_sessions; i++) { + if (this->sessions[i]) { + n += this->sessions[i]->get_num_waitables(); + } + } + return n; + } + + virtual void get_waitables(IWaitable **dst) { + dst[0] = this; + unsigned int n = 0; + for (unsigned int i = 0; i < this->max_sessions; i++) { + if (this->sessions[i]) { + this->sessions[i]->get_waitables(&dst[1 + n]); + n += this->sessions[i]->get_num_waitables(); + } + } + } + + virtual void delete_child(IWaitable *child) { + unsigned int i; + for (i = 0; i < this->max_sessions; i++) { + if (this->sessions[i] == child) { + break; + } + } + + if (i == this->max_sessions) { + /* TODO: Panic, because this isn't our child. */ + } else { + delete this->sessions[i]; + this->sessions[i] = NULL; + this->num_sessions--; + } + } + + virtual Handle get_handle() { + return this->port_handle; + } + + virtual Result handle_signaled(u64 timeout) { + /* If this server's port was signaled, accept a new session. */ + Handle session_h; + svcAcceptSession(&session_h, this->port_handle); + + if (this->num_sessions >= this->max_sessions) { + svcCloseHandle(session_h); + return 0x10601; + } + + unsigned int i; + for (i = 0; i < this->max_sessions; i++) { + if (this->sessions[i] == NULL) { + break; + } + } + + this->sessions[i] = new ServiceSession(this, session_h, 0); + this->sessions[i]->set_parent(this); + this->num_sessions++; + return 0; + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp b/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp new file mode 100644 index 000000000..17c91d639 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp @@ -0,0 +1,13 @@ +#pragma once +#include +#include "iserver.hpp" + +template +class ManagedPortServer : public IServer { + private: + virtual Result register_self(const char *service_name) { + return svcManageNamedPort(&this->port_handle, service_name, this->max_sessions); + } + public: + ManagedPortServer(const char *service_name, unsigned int max_s) : IServer(service_name, max_s) { } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp b/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp index 7de6431d0..656718813 100644 --- a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp @@ -1,112 +1,13 @@ #pragma once #include -#include - -#include "iserviceobject.hpp" -#include "iwaitable.hpp" -#include "servicesession.hpp" +#include "iserver.hpp" template -class ServiceSession; - -template -class ServiceServer : public IWaitable { - static_assert(std::is_base_of::value, "Service Objects must derive from IServiceObject"); - - Handle port_handle; - unsigned int max_sessions; - unsigned int num_sessions; - ServiceSession **sessions; - +class ServiceServer : public IServer { + private: + virtual Result register_self(const char *service_name) { + return smRegisterService(&this->port_handle, service_name, false, this->max_sessions); + } public: - ServiceServer(const char *service_name, unsigned int max_s) : max_sessions(max_s) { - if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) { - /* TODO: Panic. */ - } - this->sessions = new ServiceSession *[this->max_sessions]; - for (unsigned int i = 0; i < this->max_sessions; i++) { - this->sessions[i] = NULL; - } - this->num_sessions = 0; - } - - virtual ~ServiceServer() { - for (unsigned int i = 0; i < this->max_sessions; i++) { - if (this->sessions[i]) { - delete this->sessions[i]; - } - - delete this->sessions; - } - - if (port_handle) { - svcCloseHandle(port_handle); - } - } - - /* IWaitable */ - virtual unsigned int get_num_waitables() { - unsigned int n = 1; - for (unsigned int i = 0; i < this->max_sessions; i++) { - if (this->sessions[i]) { - n += this->sessions[i]->get_num_waitables(); - } - } - return n; - } - - virtual void get_waitables(IWaitable **dst) { - dst[0] = this; - unsigned int n = 0; - for (unsigned int i = 0; i < this->max_sessions; i++) { - if (this->sessions[i]) { - this->sessions[i]->get_waitables(&dst[1 + n]); - n += this->sessions[i]->get_num_waitables(); - } - } - } - - virtual void delete_child(IWaitable *child) { - unsigned int i; - for (i = 0; i < this->max_sessions; i++) { - if (this->sessions[i] == child) { - break; - } - } - - if (i == this->max_sessions) { - /* TODO: Panic, because this isn't our child. */ - } else { - delete this->sessions[i]; - this->sessions[i] = NULL; - this->num_sessions--; - } - } - - virtual Handle get_handle() { - return this->port_handle; - } - - virtual Result handle_signaled(u64 timeout) { - /* If this server's port was signaled, accept a new session. */ - Handle session_h; - svcAcceptSession(&session_h, this->port_handle); - - if (this->num_sessions >= this->max_sessions) { - svcCloseHandle(session_h); - return 0x10601; - } - - unsigned int i; - for (i = 0; i < this->max_sessions; i++) { - if (this->sessions[i] == NULL) { - break; - } - } - - this->sessions[i] = new ServiceSession(this, session_h, 0); - this->sessions[i]->set_parent(this); - this->num_sessions++; - return 0; - } + ServiceServer(const char *service_name, unsigned int max_s) : IServer(service_name, max_s) { } }; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp b/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp index e7430de2e..996a228fe 100644 --- a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp @@ -5,7 +5,7 @@ #include "ipc_templating.hpp" #include "iserviceobject.hpp" #include "iwaitable.hpp" -#include "serviceserver.hpp" +#include "iserver.hpp" enum IpcControlCommand { IpcCtrl_Cmd_ConvertCurrentObjectToDomain = 0, @@ -18,14 +18,14 @@ enum IpcControlCommand { #define POINTER_BUFFER_SIZE_MAX 0xFFFF template -class ServiceServer; +class IServer; template class ServiceSession : public IWaitable { static_assert(std::is_base_of::value, "Service Objects must derive from IServiceObject"); T *service_object; - ServiceServer *server; + IServer *server; Handle server_handle; Handle client_handle; char pointer_buffer[0x400]; @@ -33,7 +33,7 @@ class ServiceSession : public IWaitable { static_assert(sizeof(pointer_buffer) <= POINTER_BUFFER_SIZE_MAX, "Incorrect Size for PointerBuffer!"); public: - ServiceSession(ServiceServer *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) { + ServiceSession(IServer *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) { this->service_object = new T(); }