mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Tweak how the Horizon class and service manager work
- Store IServiceObjects in the service manager that return the usable objects instead of storing the objects directly - Register FS services in the service manager instead of giving them special treatment - Give each created HorizonClient its own "process ID"
This commit is contained in:
parent
deaf111ac3
commit
071b608f5f
15 changed files with 164 additions and 111 deletions
|
@ -34,7 +34,7 @@ namespace LibHac.Bcat
|
||||||
|
|
||||||
IServiceCreator service = GetServiceCreator(type);
|
IServiceCreator service = GetServiceCreator(type);
|
||||||
|
|
||||||
Result rc = Hos.Sm.RegisterService(service, name);
|
Result rc = Hos.Sm.RegisterService(new BcatServiceObject(service), name);
|
||||||
if (rc.IsFailure())
|
if (rc.IsFailure())
|
||||||
{
|
{
|
||||||
throw new HorizonResultException(rc, "Abort");
|
throw new HorizonResultException(rc, "Abort");
|
||||||
|
|
20
src/LibHac/Bcat/Detail/Ipc/BcatServiceObject.cs
Normal file
20
src/LibHac/Bcat/Detail/Ipc/BcatServiceObject.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using LibHac.Sm;
|
||||||
|
|
||||||
|
namespace LibHac.Bcat.Detail.Ipc
|
||||||
|
{
|
||||||
|
internal class BcatServiceObject : IServiceObject
|
||||||
|
{
|
||||||
|
private IServiceCreator _serviceCreator;
|
||||||
|
|
||||||
|
public BcatServiceObject(IServiceCreator serviceCreator)
|
||||||
|
{
|
||||||
|
_serviceCreator = serviceCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result GetServiceObject(out object serviceObject)
|
||||||
|
{
|
||||||
|
serviceObject = _serviceCreator;
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
|
using LibHac.Diag;
|
||||||
using LibHac.Fs.Accessors;
|
using LibHac.Fs.Accessors;
|
||||||
using LibHac.Fs.Fsa;
|
using LibHac.Fs.Fsa;
|
||||||
using LibHac.FsSrv;
|
using LibHac.FsSrv;
|
||||||
|
@ -11,7 +12,7 @@ namespace LibHac.Fs
|
||||||
{
|
{
|
||||||
public partial class FileSystemClient
|
public partial class FileSystemClient
|
||||||
{
|
{
|
||||||
private FileSystemServer FsSrv { get; }
|
private HorizonClient Hos { get; }
|
||||||
private IFileSystemProxy FsProxy { get; set; }
|
private IFileSystemProxy FsProxy { get; set; }
|
||||||
|
|
||||||
private readonly object _fspInitLocker = new object();
|
private readonly object _fspInitLocker = new object();
|
||||||
|
@ -26,22 +27,17 @@ namespace LibHac.Fs
|
||||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileSystemClient(FileSystemServer fsServer, ITimeSpanGenerator timer)
|
public FileSystemClient(HorizonClient horizonClient)
|
||||||
{
|
{
|
||||||
FsSrv = fsServer;
|
Hos = horizonClient;
|
||||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
Time = horizonClient.Time;
|
||||||
}
|
|
||||||
|
|
||||||
internal FileSystemClient(FileSystemServer fsServer, IFileSystemProxy fsProxy, ITimeSpanGenerator timer)
|
Assert.NotNull(Time);
|
||||||
{
|
|
||||||
FsSrv = fsServer;
|
|
||||||
FsProxy = fsProxy;
|
|
||||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasFileSystemServer()
|
public bool HasFileSystemServer()
|
||||||
{
|
{
|
||||||
return FsSrv != null;
|
return Hos != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFileSystemProxy GetFileSystemProxyServiceObject()
|
public IFileSystemProxy GetFileSystemProxyServiceObject()
|
||||||
|
@ -57,8 +53,16 @@ namespace LibHac.Fs
|
||||||
throw new InvalidOperationException("Client was not initialized with a server object.");
|
throw new InvalidOperationException("Client was not initialized with a server object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
FsProxy = FsSrv.CreateFileSystemProxyService();
|
Result rc = Hos.Sm.GetService(out IFileSystemProxy fsProxy, "fsp-srv");
|
||||||
|
|
||||||
|
if (rc.IsFailure())
|
||||||
|
{
|
||||||
|
throw new HorizonResultException(rc, "Failed to create file system proxy service object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fsProxy.SetCurrentProcess(Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||||
|
|
||||||
|
FsProxy = fsProxy;
|
||||||
return FsProxy;
|
return FsProxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace LibHac.FsSrv
|
||||||
public class FileSystemProxy : IFileSystemProxy
|
public class FileSystemProxy : IFileSystemProxy
|
||||||
{
|
{
|
||||||
private FileSystemProxyCore FsProxyCore { get; }
|
private FileSystemProxyCore FsProxyCore { get; }
|
||||||
internal FileSystemServer FsServer { get; }
|
internal HorizonClient Hos { get; }
|
||||||
|
|
||||||
public ulong CurrentProcess { get; private set; }
|
public ulong CurrentProcess { get; private set; }
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@ namespace LibHac.FsSrv
|
||||||
public FsPath SaveDataRootPath { get; }
|
public FsPath SaveDataRootPath { get; }
|
||||||
public bool AutoCreateSaveData { get; private set; }
|
public bool AutoCreateSaveData { get; private set; }
|
||||||
|
|
||||||
internal FileSystemProxy(FileSystemProxyCore fsProxyCore, FileSystemServer fsServer)
|
internal FileSystemProxy(HorizonClient horizonClient, FileSystemProxyCore fsProxyCore)
|
||||||
{
|
{
|
||||||
FsProxyCore = fsProxyCore;
|
FsProxyCore = fsProxyCore;
|
||||||
FsServer = fsServer;
|
Hos = horizonClient;
|
||||||
|
|
||||||
CurrentProcess = ulong.MaxValue;
|
CurrentProcess = ulong.MaxValue;
|
||||||
SaveDataSize = 0x2000000;
|
SaveDataSize = 0x2000000;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using LibHac.Fs;
|
||||||
using LibHac.Fs.Impl;
|
using LibHac.Fs.Impl;
|
||||||
using LibHac.Fs.Shim;
|
using LibHac.Fs.Shim;
|
||||||
using LibHac.FsSrv.Creators;
|
using LibHac.FsSrv.Creators;
|
||||||
|
using LibHac.Sm;
|
||||||
|
|
||||||
namespace LibHac.FsSrv
|
namespace LibHac.FsSrv
|
||||||
{
|
{
|
||||||
|
@ -13,15 +14,17 @@ namespace LibHac.FsSrv
|
||||||
private FileSystemProxyCore FsProxyCore { get; }
|
private FileSystemProxyCore FsProxyCore { get; }
|
||||||
|
|
||||||
/// <summary>The client instance to be used for internal operations like save indexer access.</summary>
|
/// <summary>The client instance to be used for internal operations like save indexer access.</summary>
|
||||||
public FileSystemClient FsClient { get; }
|
public HorizonClient Hos { get; }
|
||||||
|
|
||||||
public bool IsDebugMode { get; }
|
public bool IsDebugMode { get; }
|
||||||
private ITimeSpanGenerator Timer { get; }
|
private ITimeSpanGenerator Timer { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="FileSystemServer"/>.
|
/// Creates a new <see cref="FileSystemServer"/> and registers its services using the provided HOS client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="horizonClient">The <see cref="HorizonClient"/> that will be used by this server.</param>
|
||||||
/// <param name="config">The configuration for the created <see cref="FileSystemServer"/>.</param>
|
/// <param name="config">The configuration for the created <see cref="FileSystemServer"/>.</param>
|
||||||
public FileSystemServer(FileSystemServerConfig config)
|
public FileSystemServer(HorizonClient horizonClient, FileSystemServerConfig config)
|
||||||
{
|
{
|
||||||
if (config.FsCreators == null)
|
if (config.FsCreators == null)
|
||||||
throw new ArgumentException("FsCreators must not be null");
|
throw new ArgumentException("FsCreators must not be null");
|
||||||
|
@ -29,6 +32,8 @@ namespace LibHac.FsSrv
|
||||||
if (config.DeviceOperator == null)
|
if (config.DeviceOperator == null)
|
||||||
throw new ArgumentException("DeviceOperator must not be null");
|
throw new ArgumentException("DeviceOperator must not be null");
|
||||||
|
|
||||||
|
Hos = horizonClient;
|
||||||
|
|
||||||
IsDebugMode = false;
|
IsDebugMode = false;
|
||||||
|
|
||||||
ExternalKeySet externalKeySet = config.ExternalKeySet ?? new ExternalKeySet();
|
ExternalKeySet externalKeySet = config.ExternalKeySet ?? new ExternalKeySet();
|
||||||
|
@ -41,17 +46,19 @@ namespace LibHac.FsSrv
|
||||||
};
|
};
|
||||||
|
|
||||||
FsProxyCore = new FileSystemProxyCore(fspConfig, externalKeySet, config.DeviceOperator);
|
FsProxyCore = new FileSystemProxyCore(fspConfig, externalKeySet, config.DeviceOperator);
|
||||||
var fsProxy = new FileSystemProxy(FsProxyCore, this);
|
|
||||||
FsClient = new FileSystemClient(this, fsProxy, Timer);
|
|
||||||
|
|
||||||
// NS usually takes care of this
|
FsProxyCore.SetSaveDataIndexerManager(new SaveDataIndexerManager(Hos.Fs, SaveIndexerId,
|
||||||
if (FsClient.IsSdCardInserted())
|
|
||||||
FsClient.SetSdCardAccessibility(true);
|
|
||||||
|
|
||||||
FsProxyCore.SetSaveDataIndexerManager(new SaveDataIndexerManager(FsClient, SaveIndexerId,
|
|
||||||
new ArrayPoolMemoryResource(), new SdHandleManager(), false));
|
new ArrayPoolMemoryResource(), new SdHandleManager(), false));
|
||||||
|
|
||||||
|
FileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||||
|
fsProxy.SetCurrentProcess(Hos.Os.GetCurrentProcessId().Value).IgnoreResult();
|
||||||
fsProxy.CleanUpTemporaryStorage().IgnoreResult();
|
fsProxy.CleanUpTemporaryStorage().IgnoreResult();
|
||||||
|
|
||||||
|
Hos.Sm.RegisterService(new FileSystemProxyService(this), "fsp-srv").IgnoreResult();
|
||||||
|
|
||||||
|
// NS usually takes care of this
|
||||||
|
if (Hos.Fs.IsSdCardInserted())
|
||||||
|
Hos.Fs.SetSdCardAccessibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -69,12 +76,35 @@ namespace LibHac.FsSrv
|
||||||
/// <returns>The created <see cref="FileSystemClient"/>.</returns>
|
/// <returns>The created <see cref="FileSystemClient"/>.</returns>
|
||||||
public FileSystemClient CreateFileSystemClient(ITimeSpanGenerator timer)
|
public FileSystemClient CreateFileSystemClient(ITimeSpanGenerator timer)
|
||||||
{
|
{
|
||||||
return new FileSystemClient(this, timer);
|
return new FileSystemClient(Hos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFileSystemProxy CreateFileSystemProxyService()
|
private FileSystemProxy GetFileSystemProxyServiceObject()
|
||||||
{
|
{
|
||||||
return new FileSystemProxy(FsProxyCore, this);
|
return new FileSystemProxy(Hos, FsProxyCore);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsCurrentProcess(ulong processId)
|
||||||
|
{
|
||||||
|
ulong currentId = Hos.Os.GetCurrentProcessId().Value;
|
||||||
|
|
||||||
|
return processId == currentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileSystemProxyService : IServiceObject
|
||||||
|
{
|
||||||
|
private readonly FileSystemServer _server;
|
||||||
|
|
||||||
|
public FileSystemProxyService(FileSystemServer server)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result GetServiceObject(out object serviceObject)
|
||||||
|
{
|
||||||
|
serviceObject = _server.GetFileSystemProxyServiceObject();
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace LibHac.FsSrv.Impl
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = FsProxy.FsServer.FsClient.CreateSystemSaveData(SaveDataId, SaveDataSize, SaveJournalSize,
|
rc = FsProxy.Hos.Fs.CreateSystemSaveData(SaveDataId, SaveDataSize, SaveJournalSize,
|
||||||
SaveDataFlags.None);
|
SaveDataFlags.None);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,12 +183,6 @@ namespace LibHac.FsSrv.Impl
|
||||||
return initialProcessIdLowerBound >= processId && processId <= initialProcessIdUpperBound;
|
return initialProcessIdLowerBound >= processId && processId <= initialProcessIdUpperBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsCurrentProcess(ulong processId)
|
|
||||||
{
|
|
||||||
// Todo: Don't use hardcoded value
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ProgramInfo CreateProgramInfoForInitialProcess(FileSystemServer fsServer)
|
internal static ProgramInfo CreateProgramInfoForInitialProcess(FileSystemServer fsServer)
|
||||||
{
|
{
|
||||||
return new ProgramInfo(fsServer, InitialProcessAccessControlDataHeader,
|
return new ProgramInfo(fsServer, InitialProcessAccessControlDataHeader,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using LibHac.Common;
|
using System.Threading;
|
||||||
using LibHac.Fs;
|
using LibHac.Bcat;
|
||||||
using LibHac.FsSrv;
|
using LibHac.FsSrv;
|
||||||
using LibHac.FsSrv.Creators;
|
using LibHac.Os;
|
||||||
using LibHac.Sm;
|
using LibHac.Sm;
|
||||||
|
|
||||||
namespace LibHac
|
namespace LibHac
|
||||||
|
@ -9,63 +9,32 @@ namespace LibHac
|
||||||
public class Horizon
|
public class Horizon
|
||||||
{
|
{
|
||||||
internal ITimeSpanGenerator Time { get; }
|
internal ITimeSpanGenerator Time { get; }
|
||||||
private FileSystemServer FileSystemServer { get; set; }
|
|
||||||
internal ServiceManager ServiceManager { get; }
|
internal ServiceManager ServiceManager { get; }
|
||||||
|
|
||||||
private readonly object _initLocker = new object();
|
// long instead of ulong because the ulong Interlocked.Increment overload
|
||||||
|
// wasn't added until .NET 5
|
||||||
|
private long _currentProcessId;
|
||||||
|
|
||||||
public Horizon(ITimeSpanGenerator timer)
|
public Horizon(ITimeSpanGenerator timer, FileSystemServerConfig fsServerConfig)
|
||||||
{
|
{
|
||||||
|
_currentProcessId = 0;
|
||||||
|
|
||||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
Time = timer ?? new StopWatchTimeSpanGenerator();
|
||||||
ServiceManager = new ServiceManager(this);
|
ServiceManager = new ServiceManager();
|
||||||
|
|
||||||
|
// ReSharper disable ObjectCreationAsStatement
|
||||||
|
new FileSystemServer(CreateHorizonClient(), fsServerConfig);
|
||||||
|
new BcatServer(CreateHorizonClient());
|
||||||
|
// ReSharper restore ObjectCreationAsStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
public Horizon(ITimeSpanGenerator timer, FileSystemServer fsServer)
|
public HorizonClient CreateHorizonClient()
|
||||||
{
|
{
|
||||||
Time = timer ?? new StopWatchTimeSpanGenerator();
|
ulong processId = (ulong)Interlocked.Increment(ref _currentProcessId);
|
||||||
FileSystemServer = fsServer;
|
|
||||||
ServiceManager = new ServiceManager(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Result OpenFileSystemClient(out FileSystemClient client)
|
// Todo: Register process with FS
|
||||||
{
|
|
||||||
if (FileSystemServer is null)
|
|
||||||
{
|
|
||||||
client = default;
|
|
||||||
return ResultLibHac.ServiceNotInitialized.Log();
|
|
||||||
}
|
|
||||||
|
|
||||||
client = FileSystemServer.CreateFileSystemClient();
|
return new HorizonClient(this, new ProcessId(processId));
|
||||||
return Result.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result CreateHorizonClient(out HorizonClient client)
|
|
||||||
{
|
|
||||||
Result rc = OpenFileSystemClient(out FileSystemClient fsClient);
|
|
||||||
if (rc.IsFailure())
|
|
||||||
{
|
|
||||||
client = default;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = new HorizonClient(this, fsClient);
|
|
||||||
return Result.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InitializeFileSystemServer(FileSystemCreators fsCreators, IDeviceOperator deviceOperator)
|
|
||||||
{
|
|
||||||
if (FileSystemServer != null) return;
|
|
||||||
|
|
||||||
lock (_initLocker)
|
|
||||||
{
|
|
||||||
if (FileSystemServer != null) return;
|
|
||||||
|
|
||||||
var config = new FileSystemServerConfig();
|
|
||||||
config.FsCreators = fsCreators;
|
|
||||||
config.DeviceOperator = deviceOperator;
|
|
||||||
|
|
||||||
FileSystemServer = new FileSystemServer(config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using LibHac.Arp;
|
using LibHac.Arp;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
using LibHac.Os;
|
||||||
using LibHac.Sm;
|
using LibHac.Sm;
|
||||||
|
|
||||||
namespace LibHac
|
namespace LibHac
|
||||||
|
@ -9,19 +10,25 @@ namespace LibHac
|
||||||
{
|
{
|
||||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||||
private Horizon Horizon { get; }
|
private Horizon Horizon { get; }
|
||||||
|
internal ProcessId ProcessId { get; }
|
||||||
|
|
||||||
private Lazy<ArpClient> ArpLazy { get; }
|
private Lazy<ArpClient> ArpLazy { get; }
|
||||||
|
|
||||||
public FileSystemClient Fs { get; }
|
public FileSystemClient Fs { get; }
|
||||||
public ServiceManagerClient Sm { get; }
|
public ServiceManagerClient Sm { get; }
|
||||||
|
public OsClient Os { get; }
|
||||||
public ArpClient Arp => ArpLazy.Value;
|
public ArpClient Arp => ArpLazy.Value;
|
||||||
|
|
||||||
internal HorizonClient(Horizon horizon, FileSystemClient fsClient)
|
public ITimeSpanGenerator Time => Horizon.Time;
|
||||||
|
|
||||||
|
internal HorizonClient(Horizon horizon, ProcessId processId)
|
||||||
{
|
{
|
||||||
Horizon = horizon;
|
Horizon = horizon;
|
||||||
|
ProcessId = processId;
|
||||||
|
|
||||||
Fs = fsClient;
|
Fs = new FileSystemClient(this);
|
||||||
Sm = new ServiceManagerClient(horizon.ServiceManager);
|
Sm = new ServiceManagerClient(horizon.ServiceManager);
|
||||||
|
Os = new OsClient(this);
|
||||||
|
|
||||||
ArpLazy = new Lazy<ArpClient>(InitArpClient, true);
|
ArpLazy = new Lazy<ArpClient>(InitArpClient, true);
|
||||||
}
|
}
|
||||||
|
|
17
src/LibHac/Os/OsClient.cs
Normal file
17
src/LibHac/Os/OsClient.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace LibHac.Os
|
||||||
|
{
|
||||||
|
public class OsClient
|
||||||
|
{
|
||||||
|
private HorizonClient Hos { get; }
|
||||||
|
|
||||||
|
internal OsClient(HorizonClient horizonClient)
|
||||||
|
{
|
||||||
|
Hos = horizonClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessId GetCurrentProcessId()
|
||||||
|
{
|
||||||
|
return Hos.ProcessId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/LibHac/Os/ProcessId.cs
Normal file
11
src/LibHac/Os/ProcessId.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace LibHac.Os
|
||||||
|
{
|
||||||
|
public readonly struct ProcessId
|
||||||
|
{
|
||||||
|
public static ProcessId InvalidId => new ProcessId(ulong.MaxValue);
|
||||||
|
|
||||||
|
public readonly ulong Value;
|
||||||
|
|
||||||
|
public ProcessId(ulong value) => Value = value;
|
||||||
|
}
|
||||||
|
}
|
9
src/LibHac/Sm/IServiceObject.cs
Normal file
9
src/LibHac/Sm/IServiceObject.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace LibHac.Sm
|
||||||
|
{
|
||||||
|
// This interface is being used as a stop-gap solution so we can
|
||||||
|
// have at least some sort of service system for now
|
||||||
|
public interface IServiceObject
|
||||||
|
{
|
||||||
|
Result GetServiceObject(out object serviceObject);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,7 @@ namespace LibHac.Sm
|
||||||
// isn't blocked waiting for something better.
|
// isn't blocked waiting for something better.
|
||||||
internal class ServiceManager
|
internal class ServiceManager
|
||||||
{
|
{
|
||||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
private Dictionary<ServiceName, IServiceObject> Services { get; } = new Dictionary<ServiceName, IServiceObject>();
|
||||||
private Horizon Horizon { get; }
|
|
||||||
private Dictionary<ServiceName, object> Services { get; } = new Dictionary<ServiceName, object>();
|
|
||||||
|
|
||||||
public ServiceManager(Horizon horizon)
|
|
||||||
{
|
|
||||||
Horizon = horizon;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Result GetService(out object serviceObject, ServiceName serviceName)
|
internal Result GetService(out object serviceObject, ServiceName serviceName)
|
||||||
{
|
{
|
||||||
|
@ -27,20 +20,20 @@ namespace LibHac.Sm
|
||||||
Result rc = ValidateServiceName(serviceName);
|
Result rc = ValidateServiceName(serviceName);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if (!Services.TryGetValue(serviceName, out serviceObject))
|
if (!Services.TryGetValue(serviceName, out IServiceObject service))
|
||||||
{
|
{
|
||||||
return ResultSf.RequestDeferredByUser.Log();
|
return ResultSf.RequestDeferredByUser.Log();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Success;
|
return service.GetServiceObject(out serviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Result RegisterService(object serviceObject, ServiceName serviceName)
|
internal Result RegisterService(IServiceObject service, ServiceName serviceName)
|
||||||
{
|
{
|
||||||
Result rc = ValidateServiceName(serviceName);
|
Result rc = ValidateServiceName(serviceName);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if (!Services.TryAdd(serviceName, serviceObject))
|
if (!Services.TryAdd(serviceName, service))
|
||||||
{
|
{
|
||||||
return ResultSm.AlreadyRegistered.Log();
|
return ResultSm.AlreadyRegistered.Log();
|
||||||
}
|
}
|
||||||
|
@ -53,11 +46,12 @@ namespace LibHac.Sm
|
||||||
Result rc = ValidateServiceName(serviceName);
|
Result rc = ValidateServiceName(serviceName);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
if (!Services.Remove(serviceName, out object service))
|
if (!Services.Remove(serviceName, out IServiceObject service))
|
||||||
{
|
{
|
||||||
return ResultSm.NotRegistered.Log();
|
return ResultSm.NotRegistered.Log();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once SuspiciousTypeConversion.Global
|
||||||
if (service is IDisposable disposable)
|
if (service is IDisposable disposable)
|
||||||
{
|
{
|
||||||
disposable.Dispose();
|
disposable.Dispose();
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace LibHac.Sm
|
||||||
throw new InvalidCastException("The service object is not of the specified type.");
|
throw new InvalidCastException("The service object is not of the specified type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result RegisterService(object serviceObject, ReadOnlySpan<char> name)
|
public Result RegisterService(IServiceObject serviceObject, ReadOnlySpan<char> name)
|
||||||
{
|
{
|
||||||
return Server.RegisterService(serviceObject, ServiceName.Encode(name));
|
return Server.RegisterService(serviceObject, ServiceName.Encode(name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
|
||||||
{
|
{
|
||||||
public static class FileSystemServerFactory
|
public static class FileSystemServerFactory
|
||||||
{
|
{
|
||||||
public static FileSystemServer CreateServer(bool sdCardInserted, out IFileSystem rootFs)
|
private static FileSystemClient CreateClientImpl(bool sdCardInserted, out IFileSystem rootFs)
|
||||||
{
|
{
|
||||||
rootFs = new InMemoryFileSystem();
|
rootFs = new InMemoryFileSystem();
|
||||||
|
|
||||||
|
@ -19,23 +19,21 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
|
||||||
config.DeviceOperator = defaultObjects.DeviceOperator;
|
config.DeviceOperator = defaultObjects.DeviceOperator;
|
||||||
config.ExternalKeySet = new ExternalKeySet();
|
config.ExternalKeySet = new ExternalKeySet();
|
||||||
|
|
||||||
var fsServer = new FileSystemServer(config);
|
var horizon = new Horizon(new StopWatchTimeSpanGenerator(), config);
|
||||||
|
|
||||||
return fsServer;
|
HorizonClient horizonClient = horizon.CreateHorizonClient();
|
||||||
|
|
||||||
|
return horizonClient.Fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSystemClient CreateClient(bool sdCardInserted)
|
public static FileSystemClient CreateClient(bool sdCardInserted)
|
||||||
{
|
{
|
||||||
FileSystemServer fsServer = CreateServer(sdCardInserted, out _);
|
return CreateClientImpl(sdCardInserted, out _);
|
||||||
|
|
||||||
return fsServer.CreateFileSystemClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSystemClient CreateClient(out IFileSystem rootFs)
|
public static FileSystemClient CreateClient(out IFileSystem rootFs)
|
||||||
{
|
{
|
||||||
FileSystemServer fsServer = CreateServer(false, out rootFs);
|
return CreateClientImpl(false, out rootFs);
|
||||||
|
|
||||||
return fsServer.CreateFileSystemClient();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue