servers: allow passing arguments to std::make_shared

This commit is contained in:
misson20000 2018-12-21 00:07:07 -08:00
parent 4bcea4ed5e
commit c7777422f4
2 changed files with 35 additions and 20 deletions

View File

@ -21,7 +21,7 @@
#include "sm_mitm.h" #include "sm_mitm.h"
#include "mitm_session.hpp" #include "mitm_session.hpp"
template <typename T> template <typename T, typename... Args>
class MitmServer : public IWaitable { class MitmServer : public IWaitable {
static_assert(std::is_base_of<IMitmServiceObject, T>::value, "MitM Service Objects must derive from IMitmServiceObject"); static_assert(std::is_base_of<IMitmServiceObject, T>::value, "MitM Service Objects must derive from IMitmServiceObject");
private: private:
@ -29,8 +29,14 @@ class MitmServer : public IWaitable {
unsigned int max_sessions; unsigned int max_sessions;
char mitm_name[9]; char mitm_name[9];
std::tuple<Args...> args;
template<std::size_t... I>
static std::shared_ptr<T> ConstructionDetailHelper(std::shared_ptr<Service> forward_service, u64 client_pid, std::tuple<Args...> &&tuple, std::index_sequence<I...>) {
return std::make_shared<T>(forward_service, client_pid, std::forward<Args>(std::get<I>(std::forward<std::tuple<Args...>>(tuple)))...);
}
public: public:
MitmServer(Handle *out_query_h, const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { MitmServer(Handle *out_query_h, const char *service_name, unsigned int max_s, Args... args) : port_handle(0), max_sessions(max_s), args(std::forward_as_tuple<Args>(std::forward<Args>(args))...) {
Handle tmp_hnd; Handle tmp_hnd;
Result rc = smMitMInitialize(); Result rc = smMitMInitialize();
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
@ -97,16 +103,16 @@ class MitmServer : public IWaitable {
smMitMExit(); smMitMExit();
this->GetSessionManager()->AddWaitable(new MitmSession(session_h, client_pid, forward_service, std::make_shared<T>(forward_service, client_pid))); this->GetSessionManager()->AddWaitable(new MitmSession(session_h, client_pid, forward_service, ConstructionDetailHelper(forward_service, client_pid, std::forward<std::tuple<Args...>>(args), std::index_sequence_for<Args...>())));
return 0; return 0;
} }
}; };
template<typename T> template<typename T, typename... Args>
static void AddMitmServerToManager(SessionManagerBase *manager, const char *srv_name, unsigned int max_sessions) { static void AddMitmServerToManager(SessionManagerBase *manager, const char *srv_name, unsigned int max_sessions, Args... args) {
Handle query_h; Handle query_h;
auto *srv = new MitmServer<T>(&query_h, srv_name, max_sessions); auto *srv = new MitmServer<T, Args...>(&query_h, srv_name, max_sessions, std::forward<Args>(args)...);
manager->AddSession(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>())))); manager->AddSession(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>()))));
manager->AddWaitable(srv); manager->AddWaitable(srv);
} }

View File

@ -17,18 +17,27 @@
#pragma once #pragma once
#include <switch.h> #include <switch.h>
#include<tuple>
#include "iwaitable.hpp" #include "iwaitable.hpp"
#include "ipc.hpp" #include "ipc.hpp"
template<typename T> template<typename T, typename... Args>
class IServer : public IWaitable { class IServer : 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");
protected: protected:
Handle port_handle; Handle port_handle;
unsigned int max_sessions; unsigned int max_sessions;
private:
std::tuple<Args...> args;
template<std::size_t... I>
static std::shared_ptr<T> ConstructionDetailHelper(std::tuple<Args...> &&tuple, std::index_sequence<I...>) {
return std::make_shared<T>(std::forward<Args>(std::get<I>(std::forward<std::tuple<Args...>>(tuple)))...);
}
public: public:
IServer(unsigned int max_s) : port_handle(0), max_sessions(max_s) { } IServer(unsigned int max_s, Args... args) : port_handle(0), max_sessions(max_s), args(std::forward_as_tuple<Args>(std::forward<Args>(args))...) { }
virtual ~IServer() { virtual ~IServer() {
if (port_handle) { if (port_handle) {
@ -53,35 +62,35 @@ class IServer : public IWaitable {
return rc; return rc;
} }
this->GetSessionManager()->AddSession(session_h, std::move(ServiceObjectHolder(std::move(std::make_shared<T>())))); this->GetSessionManager()->AddSession(session_h, std::move(ServiceObjectHolder(std::move(ConstructionDetailHelper(std::forward<std::tuple<Args...>>(args), std::index_sequence_for<Args...>())))));
return 0; return 0;
} }
}; };
template <typename T> template <typename T, typename... Args>
class ServiceServer : public IServer<T> { class ServiceServer : public IServer<T, Args...> {
public: public:
ServiceServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { ServiceServer(const char *service_name, unsigned int max_s, Args... args) : IServer<T, Args...>(max_s, std::forward<Args>(args)...) {
if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) { if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) {
/* TODO: Panic. */ /* TODO: Panic. */
} }
} }
}; };
template <typename T> template <typename T, typename... Args>
class ExistingPortServer : public IServer<T> { class ExistingPortServer : public IServer<T, Args...> {
public: public:
ExistingPortServer(Handle port_h, unsigned int max_s) : IServer<T>(max_s) { ExistingPortServer(Handle port_h, unsigned int max_s, Args... args) : IServer<T, Args...>(max_s, args...) {
this->port_handle = port_h; this->port_handle = port_h;
} }
}; };
template <typename T> template <typename T, typename... Args>
class ManagedPortServer : public IServer<T> { class ManagedPortServer : public IServer<T, Args...> {
public: public:
ManagedPortServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { ManagedPortServer(const char *service_name, unsigned int max_s, Args... args) : IServer<T, Args...>(max_s, args...) {
if (R_FAILED(svcManageNamedPort(&this->port_handle, service_name, this->max_sessions))) { if (R_FAILED(svcManageNamedPort(&this->port_handle, service_name, this->max_sessions))) {
/* TODO: panic */ /* TODO: panic */
} }
} }
}; };