From c67f0a7c4be372174278c976233a215faef71a79 Mon Sep 17 00:00:00 2001
From: Ac_K <Acoustik666@gmail.com>
Date: Wed, 4 Sep 2019 18:09:20 +0200
Subject: [PATCH] IGeneralService Implement GetClientId and
 IsAnyInternetRequestAccepted (#749)

* IGeneralService Implement GetClientId and IsAnyInternetRequestAccepted

- Add nifm:a and nifm:u with a max sessions as comment since sm don't take care of sessions for now.
- Implement IGeneralService GetClientId based on RE (close #623).
- Implement IGeneralService IsAnyInternetRequestAccepted based on RE (close #624).
- Add some informations in IGeneralService CreateRequest.
- Fix a comment in IAccountService.

* Fix requested changes
---
 .../HOS/Services/Acc/IAccountService.cs       |  2 +-
 .../HOS/Services/Nifm/GeneralServiceDetail.cs |  8 +++
 .../Services/Nifm/GeneralServiceManager.cs    | 30 ++++++++++
 .../HOS/Services/Nifm/IGeneralService.cs      | 57 +++++++++++++++++--
 Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs     |  6 +-
 .../HOS/Services/Nifm/IStaticService.cs       |  4 +-
 Ryujinx.HLE/HOS/Services/Nifm/ResultCode.cs   |  3 +-
 7 files changed, 100 insertions(+), 10 deletions(-)
 create mode 100644 Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceDetail.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceManager.cs

diff --git a/Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs b/Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs
index f1f56a1899..4bda472ebd 100644
--- a/Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs
+++ b/Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs
@@ -110,7 +110,7 @@ namespace Ryujinx.HLE.HOS.Services.Acc
             MakeObject(context, new IProfile(userProfile));
 
             // Doesn't occur in our case.
-            // return MakeError(ErrorModule.Account, AccErr.NullObject);
+            // return ResultCode.NullObject;
 
             return ResultCode.Success;
         }
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceDetail.cs b/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceDetail.cs
new file mode 100644
index 0000000000..3be5fbeba9
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceDetail.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Nifm
+{
+    class GeneralServiceDetail
+    {
+        public int  ClientId;
+        public bool IsAnyInternetRequestAccepted;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceManager.cs b/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceManager.cs
new file mode 100644
index 0000000000..1b49229e39
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Nifm/GeneralServiceManager.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Ryujinx.HLE.HOS.Services.Nifm
+{
+    static class GeneralServiceManager
+    {
+        private static List<GeneralServiceDetail> _generalServices = new List<GeneralServiceDetail>();
+
+        public static int Count
+        {
+            get => _generalServices.Count;
+        }
+
+        public static void Add(GeneralServiceDetail generalServiceDetail)
+        {
+            _generalServices.Add(generalServiceDetail);
+        }
+
+        public static void Remove(int index)
+        {
+            _generalServices.RemoveAt(index);
+        }
+
+        public static GeneralServiceDetail Get(int clientId)
+        {
+            return _generalServices.First(item => item.ClientId == clientId);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/IGeneralService.cs b/Ryujinx.HLE/HOS/Services/Nifm/IGeneralService.cs
index ba6a2b5da8..a47e73002d 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/IGeneralService.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/IGeneralService.cs
@@ -7,19 +7,45 @@ using System.Net.Sockets;
 
 namespace Ryujinx.HLE.HOS.Services.Nifm
 {
-    class IGeneralService : IpcService
+    class IGeneralService : IpcService, IDisposable
     {
-        public IGeneralService() { }
+        private GeneralServiceDetail _generalServiceDetail;
+
+        public IGeneralService()
+        {
+            _generalServiceDetail = new GeneralServiceDetail
+            {
+                ClientId                     = GeneralServiceManager.Count,
+                IsAnyInternetRequestAccepted = true // NOTE: Why not accept any internet request?
+            };
+
+            GeneralServiceManager.Add(_generalServiceDetail);
+        }
+
+        [Command(1)]
+        // GetClientId() -> buffer<nn::nifm::ClientId, 0x1a, 4>
+        public ResultCode GetClientId(ServiceCtx context)
+        {
+            long position = context.Request.RecvListBuff[0].Position;
+            long size     = context.Request.RecvListBuff[0].Size;
+
+            context.Memory.WriteInt32(position, _generalServiceDetail.ClientId);
+
+            return ResultCode.Success;
+        }
 
         [Command(4)]
-        // CreateRequest(u32) -> object<nn::nifm::detail::IRequest>
+        // CreateRequest(u32 version) -> object<nn::nifm::detail::IRequest>
         public ResultCode CreateRequest(ServiceCtx context)
         {
-            int unknown = context.RequestData.ReadInt32();
+            uint version = context.RequestData.ReadUInt32();
 
-            MakeObject(context, new IRequest(context.Device.System));
+            MakeObject(context, new IRequest(context.Device.System, version));
 
-            Logger.PrintStub(LogClass.ServiceNifm);
+            // Doesn't occur in our case.
+            // return ResultCode.ObjectIsNull;
+
+            Logger.PrintStub(LogClass.ServiceNifm, new { version });
 
             return ResultCode.Success;
         }
@@ -43,5 +69,24 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
 
             return ResultCode.Success;
         }
+
+        [Command(21)]
+        // IsAnyInternetRequestAccepted(buffer<nn::nifm::ClientId, 0x19, 4>) -> bool
+        public ResultCode IsAnyInternetRequestAccepted(ServiceCtx context)
+        {
+            long position = context.Request.PtrBuff[0].Position;
+            long size     = context.Request.PtrBuff[0].Size;
+
+            int clientId = context.Memory.ReadInt32(position);
+
+            context.ResponseData.Write(GeneralServiceManager.Get(clientId).IsAnyInternetRequestAccepted);
+
+            return ResultCode.Success;
+        }
+
+        public void Dispose()
+        {
+            GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
index efdb5cdb45..b2884f913b 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
@@ -11,10 +11,14 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
         private KEvent _event0;
         private KEvent _event1;
 
-        public IRequest(Horizon system)
+        private uint _version;
+
+        public IRequest(Horizon system, uint version)
         {
             _event0 = new KEvent(system);
             _event1 = new KEvent(system);
+
+            _version = version;
         }
 
         [Command(0)]
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs b/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs
index c3f32c2f98..eaecc3d327 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs
@@ -1,6 +1,8 @@
 namespace Ryujinx.HLE.HOS.Services.Nifm
 {
-    [Service("nifm:u")]
+    [Service("nifm:a")] // Max sessions: 2
+    [Service("nifm:s")] // Max sessions: 16
+    [Service("nifm:u")] // Max sessions: 5
     class IStaticService : IpcService
     {
         public IStaticService(ServiceCtx context) { }
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Nifm/ResultCode.cs
index a265c048b5..c661ee81f2 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/ResultCode.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/ResultCode.cs
@@ -7,6 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
 
         Success = 0,
 
-        NoInternetConnection = (300 << ErrorCodeShift) | ModuleId
+        NoInternetConnection = (300 << ErrorCodeShift) | ModuleId,
+        ObjectIsNull         = (350 << ErrorCodeShift) | ModuleId
     }
 }
\ No newline at end of file