mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Stratosphere: ServiceServer<T> -> IServer<T> as abstract base class.
This commit is contained in:
parent
4aa93ad354
commit
044d367eda
5 changed files with 144 additions and 112 deletions
|
@ -1,8 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stratosphere/ipc_templating.hpp"
|
|
||||||
#include "stratosphere/iwaitable.hpp"
|
#include "stratosphere/iwaitable.hpp"
|
||||||
#include "stratosphere/iserviceobject.hpp"
|
#include "stratosphere/iserviceobject.hpp"
|
||||||
|
#include "stratosphere/iserver.hpp"
|
||||||
#include "stratosphere/servicesession.hpp"
|
#include "stratosphere/servicesession.hpp"
|
||||||
#include "stratosphere/serviceserver.hpp"
|
#include "stratosphere/serviceserver.hpp"
|
||||||
|
#include "stratosphere/managedportserver.hpp"
|
||||||
#include "stratosphere/waitablemanager.hpp"
|
#include "stratosphere/waitablemanager.hpp"
|
||||||
|
|
||||||
|
#include "stratosphere/ipc_templating.hpp"
|
115
stratosphere/libstratosphere/include/stratosphere/iserver.hpp
Normal file
115
stratosphere/libstratosphere/include/stratosphere/iserver.hpp
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "iserviceobject.hpp"
|
||||||
|
#include "iwaitable.hpp"
|
||||||
|
#include "servicesession.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ServiceSession;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class IServer : public IWaitable {
|
||||||
|
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
|
||||||
|
protected:
|
||||||
|
Handle port_handle;
|
||||||
|
unsigned int max_sessions;
|
||||||
|
unsigned int num_sessions;
|
||||||
|
ServiceSession<T> **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<T> *[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<T>(this, session_h, 0);
|
||||||
|
this->sessions[i]->set_parent(this);
|
||||||
|
this->num_sessions++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
#include "iserver.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ManagedPortServer : public IServer<T> {
|
||||||
|
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<T>(service_name, max_s) { }
|
||||||
|
};
|
|
@ -1,112 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <type_traits>
|
#include "iserver.hpp"
|
||||||
|
|
||||||
#include "iserviceobject.hpp"
|
|
||||||
#include "iwaitable.hpp"
|
|
||||||
#include "servicesession.hpp"
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ServiceSession;
|
class ServiceServer : public IServer<T> {
|
||||||
|
private:
|
||||||
template <typename T>
|
virtual Result register_self(const char *service_name) {
|
||||||
class ServiceServer : public IWaitable {
|
return smRegisterService(&this->port_handle, service_name, false, this->max_sessions);
|
||||||
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
|
}
|
||||||
|
|
||||||
Handle port_handle;
|
|
||||||
unsigned int max_sessions;
|
|
||||||
unsigned int num_sessions;
|
|
||||||
ServiceSession<T> **sessions;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServiceServer(const char *service_name, unsigned int max_s) : max_sessions(max_s) {
|
ServiceServer(const char *service_name, unsigned int max_s) : IServer<T>(service_name, max_s) { }
|
||||||
if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) {
|
|
||||||
/* TODO: Panic. */
|
|
||||||
}
|
|
||||||
this->sessions = new ServiceSession<T> *[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<T>(this, session_h, 0);
|
|
||||||
this->sessions[i]->set_parent(this);
|
|
||||||
this->num_sessions++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
|
@ -5,7 +5,7 @@
|
||||||
#include "ipc_templating.hpp"
|
#include "ipc_templating.hpp"
|
||||||
#include "iserviceobject.hpp"
|
#include "iserviceobject.hpp"
|
||||||
#include "iwaitable.hpp"
|
#include "iwaitable.hpp"
|
||||||
#include "serviceserver.hpp"
|
#include "iserver.hpp"
|
||||||
|
|
||||||
enum IpcControlCommand {
|
enum IpcControlCommand {
|
||||||
IpcCtrl_Cmd_ConvertCurrentObjectToDomain = 0,
|
IpcCtrl_Cmd_ConvertCurrentObjectToDomain = 0,
|
||||||
|
@ -18,14 +18,14 @@ enum IpcControlCommand {
|
||||||
#define POINTER_BUFFER_SIZE_MAX 0xFFFF
|
#define POINTER_BUFFER_SIZE_MAX 0xFFFF
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ServiceServer;
|
class IServer;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ServiceSession : public IWaitable {
|
class ServiceSession : public IWaitable {
|
||||||
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
|
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
|
||||||
|
|
||||||
T *service_object;
|
T *service_object;
|
||||||
ServiceServer<T> *server;
|
IServer<T> *server;
|
||||||
Handle server_handle;
|
Handle server_handle;
|
||||||
Handle client_handle;
|
Handle client_handle;
|
||||||
char pointer_buffer[0x400];
|
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!");
|
static_assert(sizeof(pointer_buffer) <= POINTER_BUFFER_SIZE_MAX, "Incorrect Size for PointerBuffer!");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServiceSession<T>(ServiceServer<T> *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) {
|
ServiceSession<T>(IServer<T> *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) {
|
||||||
this->service_object = new T();
|
this->service_object = new T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue