aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2020-08-18 21:24:54 +0200
committerGitHub <noreply@github.com>2020-08-18 21:24:54 +0200
commit5eb0ee3ccaf531ad4042199f848e9462efb3d8ec (patch)
treebb028768792e07a2c0e1741ec5e36baea322a7bf /Ryujinx.HLE/HOS/Services
parent5b26e4ef94afca8450f07c42393180e3c97f9c00 (diff)
account: Implement IManagerForApplication calls and IAsyncContext (#1466)
* account: Implement IManagerForApplication calls and IAsyncContext This implement: - IManagerForApplication::EnsureIdTokenCacheAsync (accordingly to RE) but the Async task is stubbed. - IAsyncContext interface (accordingly to RE). - IManagerForApplication::LoadIdTokenCache (checked with RE, and stubbed). I've tried some games but now they needs some `sfdnsres` calls, some other boots and crashes with other issues. Maybe we should disable the connection somewhere to lets the game think we are offline. I have done many attempts, without success, but since the code is here now, it's better than nothing. (I've cleaned up `using` of IGeneralService too) Closes #629 and closes #630 * change AccountId * Fix gdkchan's comments * use CompletedTask
Diffstat (limited to 'Ryujinx.HLE/HOS/Services')
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AsyncContext/AsyncExecution.cs56
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs79
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs82
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/ResultCode.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs5
6 files changed, 221 insertions, 11 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AsyncContext/AsyncExecution.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AsyncContext/AsyncExecution.cs
new file mode 100644
index 00000000..2ea92b11
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AsyncContext/AsyncExecution.cs
@@ -0,0 +1,56 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext
+{
+ class AsyncExecution
+ {
+ private readonly CancellationTokenSource _tokenSource;
+ private readonly CancellationToken _token;
+
+ public KEvent SystemEvent { get; }
+ public bool IsInitialized { get; private set; }
+ public bool IsRunning { get; private set; }
+
+ public AsyncExecution(KEvent asyncEvent)
+ {
+ SystemEvent = asyncEvent;
+
+ _tokenSource = new CancellationTokenSource();
+ _token = _tokenSource.Token;
+ }
+
+ public void Initialize(int timeout, Func<CancellationToken, Task> taskAsync)
+ {
+ Task.Run(async () =>
+ {
+ IsRunning = true;
+
+ _tokenSource.CancelAfter(timeout);
+
+ try
+ {
+ await taskAsync(_token);
+ }
+ catch (Exception ex)
+ {
+ Logger.Warning?.Print(LogClass.ServiceAcc, $"Exception: {ex.Message}");
+ }
+
+ SystemEvent.ReadableEvent.Signal();
+
+ IsRunning = false;
+ }, _token);
+
+ IsInitialized = true;
+ }
+
+ public void Cancel()
+ {
+ _tokenSource.Cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
index 9678a4ca..d1bf94e7 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
@@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
if (_applicationLaunchProperty != null)
{
- return ResultCode.ApplicationLaunchPropertyAlreadyInit;
+ return ResultCode.Unknown41;
}
// The u64 argument seems to be unused by account.
@@ -282,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
/*
if (_applicationLaunchProperty != null)
{
- return ResultCode.ApplicationLaunchPropertyAlreadyInit;
+ return ResultCode.Unknown41;
}
*/
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs
new file mode 100644
index 00000000..1bbe24f1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs
@@ -0,0 +1,79 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ class IAsyncContext : IpcService
+ {
+ AsyncExecution _asyncExecution;
+
+ public IAsyncContext(AsyncExecution asyncExecution)
+ {
+ _asyncExecution = asyncExecution;
+ }
+
+ [Command(0)]
+ // GetSystemEvent() -> handle<copy>
+ public ResultCode GetSystemEvent(ServiceCtx context)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_asyncExecution.SystemEvent.ReadableEvent, out int _systemEventHandle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_systemEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [Command(1)]
+ // Cancel()
+ public ResultCode Cancel(ServiceCtx context)
+ {
+ if (!_asyncExecution.IsInitialized)
+ {
+ return ResultCode.AsyncExecutionNotInitialized;
+ }
+
+ if (_asyncExecution.IsRunning)
+ {
+ _asyncExecution.Cancel();
+ }
+
+ return ResultCode.Success;
+ }
+
+ [Command(2)]
+ // HasDone() -> b8
+ public ResultCode HasDone(ServiceCtx context)
+ {
+ if (!_asyncExecution.IsInitialized)
+ {
+ return ResultCode.AsyncExecutionNotInitialized;
+ }
+
+ context.ResponseData.Write(_asyncExecution.SystemEvent.ReadableEvent.IsSignaled());
+
+ return ResultCode.Success;
+ }
+
+ [Command(3)]
+ // GetResult()
+ public ResultCode GetResult(ServiceCtx context)
+ {
+ if (!_asyncExecution.IsInitialized)
+ {
+ return ResultCode.AsyncExecutionNotInitialized;
+ }
+
+ if (!_asyncExecution.SystemEvent.ReadableEvent.IsSignaled())
+ {
+ return ResultCode.Unknown41;
+ }
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
index 70c5965e..54565cb1 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
@@ -1,15 +1,23 @@
using Ryujinx.Common.Logging;
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
using Ryujinx.HLE.HOS.Services.Arp;
+using System;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
class IManagerForApplication : IpcService
{
+ // TODO: Determine where and how NetworkServiceAccountId is set.
+ private const long NetworkServiceAccountId = 0xcafe;
+
private UserId _userId;
private ApplicationLaunchProperty _applicationLaunchProperty;
- private const long NetworkServiceAccountId = 0xcafe;
-
public IManagerForApplication(UserId userId, ApplicationLaunchProperty applicationLaunchProperty)
{
_userId = userId;
@@ -20,8 +28,12 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// CheckAvailability()
public ResultCode CheckAvailability(ServiceCtx context)
{
+ // NOTE: This opens the file at "su/baas/USERID_IN_UUID_STRING.dat" where USERID_IN_UUID_STRING is formatted as "%08x-%04x-%04x-%02x%02x-%08x%04x".
+ // Then it searches the Availability of Online Services related to the UserId in this file and returns it.
+
Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+ // NOTE: Even if we try to return different error codes here, the guest still needs other calls.
return ResultCode.Success;
}
@@ -29,6 +41,10 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// GetAccountId() -> nn::account::NetworkServiceAccountId
public ResultCode GetAccountId(ServiceCtx context)
{
+ // NOTE: This opens the file at "su/baas/USERID_IN_UUID_STRING.dat" (where USERID_IN_UUID_STRING is formatted
+ // as "%08x-%04x-%04x-%02x%02x-%08x%04x") in the account:/ savedata.
+ // Then it searches the NetworkServiceAccountId related to the UserId in this file and returns it.
+
Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { NetworkServiceAccountId });
context.ResponseData.Write(NetworkServiceAccountId);
@@ -36,6 +52,68 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
+ [Command(2)]
+ // EnsureIdTokenCacheAsync() -> object<nn::account::detail::IAsyncContext>
+ public ResultCode EnsureIdTokenCacheAsync(ServiceCtx context)
+ {
+ KEvent asyncEvent = new KEvent(context.Device.System.KernelContext);
+ AsyncExecution asyncExecution = new AsyncExecution(asyncEvent);
+
+ asyncExecution.Initialize(1000, EnsureIdTokenCacheAsyncImpl);
+
+ MakeObject(context, new IAsyncContext(asyncExecution));
+
+ // return ResultCode.NullObject if the IAsyncContext pointer is null. Doesn't occur in our case.
+
+ return ResultCode.Success;
+ }
+
+ private async Task EnsureIdTokenCacheAsyncImpl(CancellationToken token)
+ {
+ // NOTE: This open the file at "su/baas/USERID_IN_UUID_STRING.dat" (where USERID_IN_UUID_STRING is formatted as "%08x-%04x-%04x-%02x%02x-%08x%04x")
+ // in the "account:/" savedata.
+ // Then its read data, use dauth API with this data to get the Token Id and probably store the dauth response
+ // in "su/cache/USERID_IN_UUID_STRING.dat" (where USERID_IN_UUID_STRING is formatted as "%08x-%04x-%04x-%02x%02x-%08x%04x") in the "account:/" savedata.
+ // Since we don't support online services, we can stub it.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+
+ // TODO: Use a real function instead, with the CancellationToken.
+ await Task.CompletedTask;
+ }
+
+ [Command(3)]
+ // LoadIdTokenCache() -> (u32 id_token_cache_size, buffer<bytes, 6>)
+ public ResultCode LoadIdTokenCache(ServiceCtx context)
+ {
+ long bufferPosition = context.Request.ReceiveBuff[0].Position;
+ long bufferSize = context.Request.ReceiveBuff[0].Size;
+
+ // NOTE: This opens the file at "su/cache/USERID_IN_UUID_STRING.dat" (where USERID_IN_UUID_STRING is formatted as "%08x-%04x-%04x-%02x%02x-%08x%04x")
+ // in the "account:/" savedata and writes some data in the buffer.
+ // Since we don't support online services, we can stub it.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+
+ /*
+ if (internal_object != null)
+ {
+ if (bufferSize > 0xC00)
+ {
+ return ResultCode.InvalidIdTokenCacheBufferSize;
+ }
+ }
+ */
+
+ int idTokenCacheSize = 0;
+
+ MemoryHelper.FillWithZeros(context.Memory, bufferPosition, (int)bufferSize);
+
+ context.ResponseData.Write(idTokenCacheSize);
+
+ return ResultCode.Success;
+ }
+
[Command(130)]
// GetNintendoAccountUserResourceCacheForApplication() -> (nn::account::NintendoAccountId, buffer<nn::account::nas::NasUserBaseForApplication, 0x1a>, buffer<bytes, 6>)
public ResultCode GetNintendoAccountUserResourceCacheForApplication(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs
index cf61ed5c..f25b2acb 100644
--- a/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs
@@ -12,10 +12,12 @@ namespace Ryujinx.HLE.HOS.Services.Account
NullInputBuffer = (30 << ErrorCodeShift) | ModuleId,
InvalidInputBufferSize = (31 << ErrorCodeShift) | ModuleId,
InvalidInputBuffer = (32 << ErrorCodeShift) | ModuleId,
- ApplicationLaunchPropertyAlreadyInit = (41 << ErrorCodeShift) | ModuleId,
+ AsyncExecutionNotInitialized = (40 << ErrorCodeShift) | ModuleId,
+ Unknown41 = (41 << ErrorCodeShift) | ModuleId,
InternetRequestDenied = (59 << ErrorCodeShift) | ModuleId,
UserNotFound = (100 << ErrorCodeShift) | ModuleId,
NullObject = (302 << ErrorCodeShift) | ModuleId,
- UnknownError1 = (341 << ErrorCodeShift) | ModuleId
+ Unknown341 = (341 << ErrorCodeShift) | ModuleId,
+ InvalidIdTokenCacheBufferSize = (451 << ErrorCodeShift) | ModuleId
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs
index d3b5ce3e..1b170f4b 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs
@@ -3,12 +3,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
using System;
-using System.Diagnostics;
-using System.Linq;
-using System.Net;
using System.Net.NetworkInformation;
-using System.Net.Sockets;
-using System.Runtime.CompilerServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
{