From 3e3294e1c25ab67f967d63c1232c579ad3c1e90b Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sat, 22 Jul 2023 23:29:45 -0400
Subject: [PATCH] core: implement GetGaiStringErrorRequest, IContextRegistrar

---
 src/core/hle/service/acc/acc.cpp              |  3 +-
 src/core/hle/service/glue/ectx.cpp            | 43 ++++++++++++++++++-
 src/core/hle/service/glue/ectx.h              |  3 ++
 src/core/hle/service/sockets/bsd.cpp          |  2 +-
 src/core/hle/service/sockets/nsd.cpp          | 10 ++++-
 src/core/hle/service/sockets/nsd.h            |  1 +
 src/core/hle/service/sockets/sfdnsres.cpp     | 16 ++++++-
 src/core/hle/service/sockets/sfdnsres.h       |  1 +
 .../hle/service/sockets/sockets_translate.cpp | 38 ++++++++++++++++
 .../hle/service/sockets/sockets_translate.h   |  3 ++
 10 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6c29cb613e..2632cd3ef0 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -496,8 +496,9 @@ public:
     void LoadIdTokenCache(HLERequestContext& ctx) {
         LOG_WARNING(Service_ACC, "(STUBBED) called");
 
-        IPC::ResponseBuilder rb{ctx, 2};
+        IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(ResultSuccess);
+        rb.Push(0);
     }
 
 protected:
diff --git a/src/core/hle/service/glue/ectx.cpp b/src/core/hle/service/glue/ectx.cpp
index 1bd9314aec..6f71b62f3a 100644
--- a/src/core/hle/service/glue/ectx.cpp
+++ b/src/core/hle/service/glue/ectx.cpp
@@ -2,13 +2,48 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "core/hle/service/glue/ectx.h"
+#include "core/hle/service/ipc_helpers.h"
 
 namespace Service::Glue {
 
+// This is nn::err::context::IContextRegistrar
+class IContextRegistrar : public ServiceFramework<IContextRegistrar> {
+public:
+    IContextRegistrar(Core::System& system_) : ServiceFramework{system_, "IContextRegistrar"} {
+        // clang-format off
+        static const FunctionInfo functions[] = {
+            {0, &IContextRegistrar::Complete, "Complete"},
+        };
+        // clang-format on
+
+        RegisterHandlers(functions);
+    }
+
+    ~IContextRegistrar() override = default;
+
+private:
+    void Complete(HLERequestContext& ctx) {
+        struct InputParameters {
+            u32 unk;
+        };
+        struct OutputParameters {
+            u32 unk;
+        };
+
+        IPC::RequestParser rp{ctx};
+        [[maybe_unused]] auto input = rp.PopRaw<InputParameters>();
+        [[maybe_unused]] auto value = ctx.ReadBuffer();
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(ResultSuccess);
+        rb.Push(0);
+    }
+};
+
 ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "CreateContextRegistrar"},
+        {0, &ECTX_AW::CreateContextRegistrar, "CreateContextRegistrar"},
         {1, nullptr, "CommitContext"},
     };
     // clang-format on
@@ -18,4 +53,10 @@ ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
 
 ECTX_AW::~ECTX_AW() = default;
 
+void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system));
+}
+
 } // namespace Service::Glue
diff --git a/src/core/hle/service/glue/ectx.h b/src/core/hle/service/glue/ectx.h
index a608de053e..ffa74d8d33 100644
--- a/src/core/hle/service/glue/ectx.h
+++ b/src/core/hle/service/glue/ectx.h
@@ -15,6 +15,9 @@ class ECTX_AW final : public ServiceFramework<ECTX_AW> {
 public:
     explicit ECTX_AW(Core::System& system_);
     ~ECTX_AW() override;
+
+private:
+    void CreateContextRegistrar(HLERequestContext& ctx);
 };
 
 } // namespace Service::Glue
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index e63b0a357b..11f8efbac7 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -559,7 +559,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
 
         const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
         if (!descriptor) {
-            LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd);
+            LOG_TRACE(Service, "File descriptor handle={} is not allocated", pollfd.fd);
             pollfd.revents = PollEvents::Nval;
             return {0, Errno::SUCCESS};
         }
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index 36c6cd05cd..5dfcaabb1f 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -24,7 +24,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
     static const FunctionInfo functions[] = {
         {5, nullptr, "GetSettingUrl"},
         {10, nullptr, "GetSettingName"},
-        {11, nullptr, "GetEnvironmentIdentifier"},
+        {11, &NSD::GetEnvironmentIdentifier, "GetEnvironmentIdentifier"},
         {12, nullptr, "GetDeviceId"},
         {13, nullptr, "DeleteSettings"},
         {14, nullptr, "ImportSettings"},
@@ -103,6 +103,14 @@ void NSD::ResolveEx(HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
+void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) {
+    const std::string environment_identifier = "lp1";
+    ctx.WriteBuffer(environment_identifier);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
 void NSD::GetApplicationServerEnvironmentType(HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h
index 57760a0c80..b0cfec507f 100644
--- a/src/core/hle/service/sockets/nsd.h
+++ b/src/core/hle/service/sockets/nsd.h
@@ -19,6 +19,7 @@ public:
 private:
     void Resolve(HLERequestContext& ctx);
     void ResolveEx(HLERequestContext& ctx);
+    void GetEnvironmentIdentifier(HLERequestContext& ctx);
     void GetApplicationServerEnvironmentType(HLERequestContext& ctx);
 };
 
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 84cc79de86..22e4a6f490 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -24,7 +24,7 @@ SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"
         {2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"},
         {3, nullptr, "GetHostByAddrRequest"},
         {4, nullptr, "GetHostStringErrorRequest"},
-        {5, nullptr, "GetGaiStringErrorRequest"},
+        {5, &SFDNSRES::GetGaiStringErrorRequest, "GetGaiStringErrorRequest"},
         {6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
         {7, nullptr, "GetNameInfoRequest"},
         {8, nullptr, "RequestCancelHandleRequest"},
@@ -300,6 +300,20 @@ void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) {
     });
 }
 
+void SFDNSRES::GetGaiStringErrorRequest(HLERequestContext& ctx) {
+    struct InputParameters {
+        GetAddrInfoError gai_errno;
+    };
+    IPC::RequestParser rp{ctx};
+    auto input = rp.PopRaw<InputParameters>();
+
+    const std::string result = Translate(input.gai_errno);
+    ctx.WriteBuffer(result);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
 void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
     // Additional options are ignored
     auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h
index d99a9d5601..282ef9071f 100644
--- a/src/core/hle/service/sockets/sfdnsres.h
+++ b/src/core/hle/service/sockets/sfdnsres.h
@@ -18,6 +18,7 @@ public:
 
 private:
     void GetHostByNameRequest(HLERequestContext& ctx);
+    void GetGaiStringErrorRequest(HLERequestContext& ctx);
     void GetHostByNameRequestWithOptions(HLERequestContext& ctx);
     void GetAddrInfoRequest(HLERequestContext& ctx);
     void GetAddrInfoRequestWithOptions(HLERequestContext& ctx);
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp
index 2f9a0e39c3..c1187209ff 100644
--- a/src/core/hle/service/sockets/sockets_translate.cpp
+++ b/src/core/hle/service/sockets/sockets_translate.cpp
@@ -81,6 +81,44 @@ GetAddrInfoError Translate(Network::GetAddrInfoError error) {
     }
 }
 
+const char* Translate(GetAddrInfoError error) {
+    // https://android.googlesource.com/platform/bionic/+/085543106/libc/dns/net/getaddrinfo.c#254
+    switch (error) {
+    case GetAddrInfoError::SUCCESS:
+        return "Success";
+    case GetAddrInfoError::ADDRFAMILY:
+        return "Address family for hostname not supported";
+    case GetAddrInfoError::AGAIN:
+        return "Temporary failure in name resolution";
+    case GetAddrInfoError::BADFLAGS:
+        return "Invalid value for ai_flags";
+    case GetAddrInfoError::FAIL:
+        return "Non-recoverable failure in name resolution";
+    case GetAddrInfoError::FAMILY:
+        return "ai_family not supported";
+    case GetAddrInfoError::MEMORY:
+        return "Memory allocation failure";
+    case GetAddrInfoError::NODATA:
+        return "No address associated with hostname";
+    case GetAddrInfoError::NONAME:
+        return "hostname nor servname provided, or not known";
+    case GetAddrInfoError::SERVICE:
+        return "servname not supported for ai_socktype";
+    case GetAddrInfoError::SOCKTYPE:
+        return "ai_socktype not supported";
+    case GetAddrInfoError::SYSTEM:
+        return "System error returned in errno";
+    case GetAddrInfoError::BADHINTS:
+        return "Invalid value for hints";
+    case GetAddrInfoError::PROTOCOL:
+        return "Resolved protocol is unknown";
+    case GetAddrInfoError::OVERFLOW_:
+        return "Argument buffer overflow";
+    default:
+        return "Unknown error";
+    }
+}
+
 Network::Domain Translate(Domain domain) {
     switch (domain) {
     case Domain::Unspecified:
diff --git a/src/core/hle/service/sockets/sockets_translate.h b/src/core/hle/service/sockets/sockets_translate.h
index 694868b37e..bd6721fd3e 100644
--- a/src/core/hle/service/sockets/sockets_translate.h
+++ b/src/core/hle/service/sockets/sockets_translate.h
@@ -20,6 +20,9 @@ std::pair<s32, Errno> Translate(std::pair<s32, Network::Errno> value);
 /// Translate abstract getaddrinfo error to guest getaddrinfo error
 GetAddrInfoError Translate(Network::GetAddrInfoError value);
 
+/// Translate guest error to string
+const char* Translate(GetAddrInfoError value);
+
 /// Translate guest domain to abstract domain
 Network::Domain Translate(Domain domain);