From 12dc05032b1c8dfdb000faf1ec883abff045cede Mon Sep 17 00:00:00 2001
From: FearlessTobi <thm.frey@gmail.com>
Date: Sun, 7 Aug 2022 23:54:51 +0200
Subject: [PATCH 1/3] ldn: Add better stubs and more data types

Co-Authored-By: Narr the Reg <5944268+german77@users.noreply.github.com>
Co-Authored-By: Morph <39850852+Morph1984@users.noreply.github.com>
---
 src/core/CMakeLists.txt                |   3 +-
 src/core/hle/service/ldn/errors.h      |  12 -
 src/core/hle/service/ldn/ldn.cpp       | 433 +++++++++++++++++++++----
 src/core/hle/service/ldn/ldn.h         |  73 +++++
 src/core/hle/service/ldn/ldn_results.h |  28 ++
 src/core/hle/service/ldn/ldn_types.h   | 298 +++++++++++++++++
 6 files changed, 774 insertions(+), 73 deletions(-)
 delete mode 100644 src/core/hle/service/ldn/errors.h
 create mode 100644 src/core/hle/service/ldn/ldn_results.h
 create mode 100644 src/core/hle/service/ldn/ldn_types.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9dbe5bdca..d314ff1ce 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -504,9 +504,10 @@ add_library(core STATIC
     hle/service/jit/jit.h
     hle/service/lbl/lbl.cpp
     hle/service/lbl/lbl.h
-    hle/service/ldn/errors.h
+    hle/service/ldn/ldn_results.h
     hle/service/ldn/ldn.cpp
     hle/service/ldn/ldn.h
+    hle/service/ldn/ldn_types.h
     hle/service/ldr/ldr.cpp
     hle/service/ldr/ldr.h
     hle/service/lm/lm.cpp
diff --git a/src/core/hle/service/ldn/errors.h b/src/core/hle/service/ldn/errors.h
deleted file mode 100644
index 972a74806..000000000
--- a/src/core/hle/service/ldn/errors.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/result.h"
-
-namespace Service::LDN {
-
-constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22};
-
-} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 125d4dc4c..c8e1898f4 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -3,11 +3,12 @@
 
 #include <memory>
 
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/result.h"
-#include "core/hle/service/ldn/errors.h"
+#include "core/core.h"
 #include "core/hle/service/ldn/ldn.h"
-#include "core/hle/service/sm/sm.h"
+#include "core/internal_network/network.h"
+#include "core/internal_network/network_interface.h"
+
+#undef CreateEvent
 
 namespace Service::LDN {
 
@@ -96,81 +97,393 @@ public:
     }
 };
 
-class IUserLocalCommunicationService final
-    : public ServiceFramework<IUserLocalCommunicationService> {
-public:
-    explicit IUserLocalCommunicationService(Core::System& system_)
-        : ServiceFramework{system_, "IUserLocalCommunicationService"} {
-        // clang-format off
+IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
+    : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
+      service_context{system, "IUserLocalCommunicationService"}, room_network{
+                                                                     system_.GetRoomNetwork()} {
+    // clang-format off
         static const FunctionInfo functions[] = {
             {0, &IUserLocalCommunicationService::GetState, "GetState"},
-            {1, nullptr, "GetNetworkInfo"},
+            {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
             {2, nullptr, "GetIpv4Address"},
-            {3, nullptr, "GetDisconnectReason"},
-            {4, nullptr, "GetSecurityParameter"},
-            {5, nullptr, "GetNetworkConfig"},
-            {100, nullptr, "AttachStateChangeEvent"},
-            {101, nullptr, "GetNetworkInfoLatestUpdate"},
-            {102, nullptr, "Scan"},
-            {103, nullptr, "ScanPrivate"},
+            {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
+            {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
+            {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
+            {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
+            {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
+            {102, &IUserLocalCommunicationService::Scan, "Scan"},
+            {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
             {104, nullptr, "SetWirelessControllerRestriction"},
-            {200, nullptr, "OpenAccessPoint"},
-            {201, nullptr, "CloseAccessPoint"},
-            {202, nullptr, "CreateNetwork"},
-            {203, nullptr, "CreateNetworkPrivate"},
-            {204, nullptr, "DestroyNetwork"},
+            {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
+            {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
+            {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
+            {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
+            {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
             {205, nullptr, "Reject"},
-            {206, nullptr, "SetAdvertiseData"},
-            {207, nullptr, "SetStationAcceptPolicy"},
-            {208, nullptr, "AddAcceptFilterEntry"},
+            {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
+            {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
+            {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
             {209, nullptr, "ClearAcceptFilter"},
-            {300, nullptr, "OpenStation"},
-            {301, nullptr, "CloseStation"},
-            {302, nullptr, "Connect"},
+            {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
+            {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
+            {302, &IUserLocalCommunicationService::Connect, "Connect"},
             {303, nullptr, "ConnectPrivate"},
-            {304, nullptr, "Disconnect"},
-            {400, nullptr, "Initialize"},
-            {401, nullptr, "Finalize"},
-            {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+
+            {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
+            {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
+            {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
+            {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
         };
-        // clang-format on
+    // clang-format on
 
-        RegisterHandlers(functions);
-    }
+    RegisterHandlers(functions);
 
-    void GetState(Kernel::HLERequestContext& ctx) {
-        LOG_WARNING(Service_LDN, "(STUBBED) called");
+    state_change_event =
+        service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
+}
 
-        IPC::ResponseBuilder rb{ctx, 3};
+IUserLocalCommunicationService::~IUserLocalCommunicationService() {
+    service_context.CloseEvent(state_change_event);
+}
 
-        // Indicate a network error, as we do not actually emulate LDN
-        rb.Push(static_cast<u32>(State::Error));
+void IUserLocalCommunicationService::OnEventFired() {
+    state_change_event->GetWritableEvent().Signal();
+}
 
-        rb.Push(ResultSuccess);
-    }
+void IUserLocalCommunicationService::GetState(Kernel::HLERequestContext& ctx) {
+    State state = State::Error;
+    LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
 
-    void Initialize2(Kernel::HLERequestContext& ctx) {
-        LOG_DEBUG(Service_LDN, "called");
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushEnum(state);
+}
 
-        is_initialized = true;
+void IUserLocalCommunicationService::GetNetworkInfo(Kernel::HLERequestContext& ctx) {
+    const auto write_buffer_size = ctx.GetWriteBufferSize();
 
+    if (write_buffer_size != sizeof(NetworkInfo)) {
+        LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
         IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ERROR_DISABLED);
+        rb.Push(ResultBadInput);
+        return;
     }
 
-private:
-    enum class State {
-        None,
-        Initialized,
-        AccessPointOpened,
-        AccessPointCreated,
-        StationOpened,
-        StationConnected,
-        Error,
-    };
+    NetworkInfo networkInfo{};
+    const auto rc = ResultSuccess;
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(rc);
+        return;
+    }
 
-    bool is_initialized{};
-};
+    LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
+                networkInfo.common.ssid.GetStringValue(), networkInfo.ldn.node_count);
+
+    ctx.WriteBuffer<NetworkInfo>(networkInfo);
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(rc);
+}
+
+void IUserLocalCommunicationService::GetDisconnectReason(Kernel::HLERequestContext& ctx) {
+    const auto disconnect_reason = DisconnectReason::None;
+
+    LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushEnum(disconnect_reason);
+}
+
+void IUserLocalCommunicationService::GetSecurityParameter(Kernel::HLERequestContext& ctx) {
+    SecurityParameter security_parameter;
+    NetworkInfo info;
+    const Result rc = ResultSuccess;
+
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(rc);
+        return;
+    }
+
+    security_parameter.session_id = info.network_id.session_id;
+    std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
+                sizeof(SecurityParameter::data));
+
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 10};
+    rb.Push(rc);
+    rb.PushRaw<SecurityParameter>(security_parameter);
+}
+
+void IUserLocalCommunicationService::GetNetworkConfig(Kernel::HLERequestContext& ctx) {
+    NetworkConfig config;
+    NetworkInfo info;
+    const Result rc = ResultSuccess;
+
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(rc);
+        return;
+    }
+
+    config.intent_id = info.network_id.intent_id;
+    config.channel = info.common.channel;
+    config.node_count_max = info.ldn.node_count_max;
+    config.local_communication_version = info.ldn.nodes[0].local_communication_version;
+
+    LOG_WARNING(Service_LDN,
+                "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
+                "local_communication_version={}",
+                config.intent_id.local_communication_id, config.intent_id.scene_id, config.channel,
+                config.node_count_max, config.local_communication_version);
+
+    IPC::ResponseBuilder rb{ctx, 10};
+    rb.Push(rc);
+    rb.PushRaw<NetworkConfig>(config);
+}
+
+void IUserLocalCommunicationService::AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
+    LOG_INFO(Service_LDN, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(state_change_event->GetReadableEvent());
+}
+
+void IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
+    const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
+    const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
+
+    if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
+        LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
+                  node_buffer_count);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultBadInput);
+        return;
+    }
+
+    NetworkInfo info;
+    std::vector<NodeLatestUpdate> latest_update{};
+    latest_update.resize(node_buffer_count);
+
+    const auto rc = ResultSuccess;
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(rc);
+        return;
+    }
+
+    LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
+                info.common.ssid.GetStringValue(), info.ldn.node_count);
+
+    ctx.WriteBuffer(info, 0);
+    ctx.WriteBuffer(latest_update, 1);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::Scan(Kernel::HLERequestContext& ctx) {
+    ScanImpl(ctx);
+}
+
+void IUserLocalCommunicationService::ScanPrivate(Kernel::HLERequestContext& ctx) {
+    ScanImpl(ctx, true);
+}
+
+void IUserLocalCommunicationService::ScanImpl(Kernel::HLERequestContext& ctx, bool is_private) {
+    IPC::RequestParser rp{ctx};
+    const auto channel{rp.PopEnum<WifiChannel>()};
+    const auto scan_filter{rp.PopRaw<ScanFilter>()};
+
+    const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
+
+    if (network_info_size == 0) {
+        LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultBadInput);
+        return;
+    }
+
+    u16 count = 0;
+    std::vector<NetworkInfo> networks_info{};
+    networks_info.resize(network_info_size);
+
+    LOG_WARNING(Service_LDN,
+                "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
+                channel, scan_filter.flag, scan_filter.network_type);
+
+    ctx.WriteBuffer(networks_info);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(count);
+}
+
+void IUserLocalCommunicationService::OpenAccessPoint(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::CloseAccessPoint(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::CreateNetwork(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    CreateNetworkImpl(ctx, false);
+}
+
+void IUserLocalCommunicationService::CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    CreateNetworkImpl(ctx, true);
+}
+
+void IUserLocalCommunicationService::CreateNetworkImpl(Kernel::HLERequestContext& ctx,
+                                                       bool is_private) {
+    IPC::RequestParser rp{ctx};
+
+    const auto security_config{rp.PopRaw<SecurityConfig>()};
+    [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>()
+                                                              : SecurityParameter{}};
+    const auto user_config{rp.PopRaw<UserConfig>()};
+    rp.Pop<u32>(); // Padding
+    const auto network_Config{rp.PopRaw<NetworkConfig>()};
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+void IUserLocalCommunicationService::DestroyNetwork(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::SetAdvertiseData(Kernel::HLERequestContext& ctx) {
+    std::vector<u8> read_buffer = ctx.ReadBuffer();
+
+    LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::OpenStation(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::CloseStation(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::Connect(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::RequestParser rp{ctx};
+
+    [[maybe_unused]] const auto securityConfig{rp.PopRaw<SecurityConfig>()};
+    const auto user_config{rp.PopRaw<UserConfig>()};
+    const auto local_communication_version{rp.Pop<u32>()};
+    [[maybe_unused]] const auto option{rp.Pop<u32>()};
+
+    std::vector<u8> read_buffer = ctx.ReadBuffer();
+    NetworkInfo networkInfo{};
+
+    if (read_buffer.size() != sizeof(NetworkInfo)) {
+        LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultBadInput);
+        return;
+    }
+
+    std::memcpy(&networkInfo, read_buffer.data(), read_buffer.size());
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::Disconnect(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+void IUserLocalCommunicationService::Initialize(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    const auto rc = InitializeImpl(ctx);
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(rc);
+}
+
+void IUserLocalCommunicationService::Finalize(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    is_initialized = false;
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IUserLocalCommunicationService::Initialize2(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    const auto rc = InitializeImpl(ctx);
+    if (rc.IsError()) {
+        LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(rc);
+}
+
+Result IUserLocalCommunicationService::InitializeImpl(Kernel::HLERequestContext& ctx) {
+    const auto network_interface = Network::GetSelectedNetworkInterface();
+    if (!network_interface) {
+        return ResultAirplaneModeEnabled;
+    }
+
+    is_initialized = true;
+    // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
+    return ResultAirplaneModeEnabled;
+}
 
 class LDNS final : public ServiceFramework<LDNS> {
 public:
@@ -273,7 +586,7 @@ public:
         LOG_WARNING(Service_LDN, "(STUBBED) called");
 
         IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ERROR_DISABLED);
+        rb.Push(ResultDisabled);
     }
 };
 
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index a0031ac71..331455e3f 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -3,6 +3,14 @@
 
 #pragma once
 
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/result.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/ldn/ldn_results.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/sm/sm.h"
+
 namespace Core {
 class System;
 }
@@ -16,4 +24,69 @@ namespace Service::LDN {
 /// Registers all LDN services with the specified service manager.
 void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
 
+class IUserLocalCommunicationService final
+    : public ServiceFramework<IUserLocalCommunicationService> {
+public:
+    explicit IUserLocalCommunicationService(Core::System& system_);
+    ~IUserLocalCommunicationService() override;
+
+    void GetState(Kernel::HLERequestContext& ctx);
+
+    void GetNetworkInfo(Kernel::HLERequestContext& ctx);
+
+    void GetDisconnectReason(Kernel::HLERequestContext& ctx);
+
+    void GetSecurityParameter(Kernel::HLERequestContext& ctx);
+
+    void GetNetworkConfig(Kernel::HLERequestContext& ctx);
+
+    void AttachStateChangeEvent(Kernel::HLERequestContext& ctx);
+
+    void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx);
+
+    void Scan(Kernel::HLERequestContext& ctx);
+    void ScanPrivate(Kernel::HLERequestContext& ctx);
+    void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false);
+
+    void OpenAccessPoint(Kernel::HLERequestContext& ctx);
+
+    void CloseAccessPoint(Kernel::HLERequestContext& ctx);
+
+    void CreateNetwork(Kernel::HLERequestContext& ctx);
+    void CreateNetworkPrivate(Kernel::HLERequestContext& ctx);
+    void CreateNetworkImpl(Kernel::HLERequestContext& ctx, bool is_private);
+
+    void DestroyNetwork(Kernel::HLERequestContext& ctx);
+
+    void SetAdvertiseData(Kernel::HLERequestContext& ctx);
+
+    void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx);
+
+    void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx);
+
+    void OpenStation(Kernel::HLERequestContext& ctx);
+
+    void CloseStation(Kernel::HLERequestContext& ctx);
+
+    void Disconnect(Kernel::HLERequestContext& ctx);
+
+    void Connect(Kernel::HLERequestContext& ctx);
+
+    void Initialize(Kernel::HLERequestContext& ctx);
+
+    void Finalize(Kernel::HLERequestContext& ctx);
+
+    void Initialize2(Kernel::HLERequestContext& ctx);
+    Result InitializeImpl(Kernel::HLERequestContext& ctx);
+
+private:
+    void OnEventFired();
+
+    KernelHelpers::ServiceContext service_context;
+    Kernel::KEvent* state_change_event;
+    Network::RoomNetwork& room_network;
+
+    bool is_initialized{};
+};
+
 } // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn_results.h b/src/core/hle/service/ldn/ldn_results.h
new file mode 100644
index 000000000..8b6b436b7
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_results.h
@@ -0,0 +1,28 @@
+// Copyright 2022 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::LDN {
+
+constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10};
+constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20};
+constexpr Result ResultDisabled{ErrorModule::LDN, 22};
+constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23};
+constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30};
+constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31};
+constexpr Result ResultBadState{ErrorModule::LDN, 32};
+constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33};
+constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50};
+constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65};
+constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66};
+constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67};
+constexpr Result ResultBadInput{ErrorModule::LDN, 96};
+constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97};
+constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113};
+constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
new file mode 100644
index 000000000..1132b2eb6
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -0,0 +1,298 @@
+// Copyright 2022 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <fmt/format.h>
+
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "network/network.h"
+
+namespace Service::LDN {
+
+constexpr size_t SsidLengthMax = 32;
+constexpr size_t AdvertiseDataSizeMax = 384;
+constexpr size_t UserNameBytesMax = 32;
+constexpr int NodeCountMax = 8;
+constexpr int StationCountMax = NodeCountMax - 1;
+constexpr size_t PassphraseLengthMax = 64;
+
+enum class SecurityMode : u16 {
+    All,
+    Retail,
+    Debug,
+};
+
+enum class NodeStateChange : u8 {
+    None,
+    Connect,
+    Disconnect,
+    DisconnectAndConnect,
+};
+
+inline NodeStateChange operator|(NodeStateChange a, NodeStateChange b) {
+    return static_cast<NodeStateChange>(static_cast<u8>(a) | static_cast<u8>(b));
+}
+
+inline NodeStateChange operator|=(NodeStateChange& a, NodeStateChange b) {
+    return a = a | b;
+}
+
+enum class ScanFilterFlag : u32 {
+    None = 0,
+    LocalCommunicationId = 1 << 0,
+    SessionId = 1 << 1,
+    NetworkType = 1 << 2,
+    Ssid = 1 << 4,
+    SceneId = 1 << 5,
+    IntentId = LocalCommunicationId | SceneId,
+    NetworkId = IntentId | SessionId,
+};
+
+enum class NetworkType : u32 {
+    None,
+    General,
+    Ldn,
+    All,
+};
+
+enum class PackedNetworkType : u8 {
+    None,
+    General,
+    Ldn,
+    All,
+};
+
+enum class State : u32 {
+    None,
+    Initialized,
+    AccessPointOpened,
+    AccessPointCreated,
+    StationOpened,
+    StationConnected,
+    Error,
+};
+
+enum class DisconnectReason : s16 {
+    Unknown = -1,
+    None,
+    DisconnectedByUser,
+    DisconnectedBySystem,
+    DestroyedByUser,
+    DestroyedBySystem,
+    Rejected,
+    SignalLost,
+};
+
+enum class NetworkError {
+    Unknown = -1,
+    None = 0,
+    PortUnreachable,
+    TooManyPlayers,
+    VersionTooLow,
+    VersionTooHigh,
+    ConnectFailure,
+    ConnectNotFound,
+    ConnectTimeout,
+    ConnectRejected,
+    RejectFailed,
+};
+
+enum class AcceptPolicy : u8 {
+    AcceptAll,
+    RejectAll,
+    BlackList,
+    WhiteList,
+};
+
+enum class WifiChannel : s16 {
+    Default = 0,
+    wifi24_1 = 1,
+    wifi24_6 = 6,
+    wifi24_11 = 11,
+    wifi50_36 = 36,
+    wifi50_40 = 40,
+    wifi50_44 = 44,
+    wifi50_48 = 48,
+};
+
+enum class LinkLevel : s8 {
+    Bad,
+    Low,
+    Good,
+    Excelent,
+};
+
+struct NodeLatestUpdate {
+    NodeStateChange state_change;
+    INSERT_PADDING_BYTES(0x7); // Unknown
+};
+static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size");
+
+struct SessionId {
+    u64 high;
+    u64 low;
+
+public:
+    bool operator==(const SessionId& b) const {
+        return (low == b.low) && (high == b.high);
+    }
+};
+static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
+
+struct IntentId {
+    u64 local_communication_id;
+    INSERT_PADDING_BYTES(0x2); // Reserved
+    u16 scene_id;
+    INSERT_PADDING_BYTES(0x4); // Reserved
+};
+static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
+
+struct NetworkId {
+    IntentId intent_id;
+    SessionId session_id;
+};
+static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
+
+struct Ssid {
+    u8 length;
+    std::array<char, SsidLengthMax + 1> raw;
+
+public:
+    std::string GetStringValue() const {
+        return std::string(raw.data(), length);
+    }
+};
+static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size");
+
+struct Ipv4Address {
+    union {
+        u32 raw{};
+        std::array<u8, 4> bytes;
+    };
+
+public:
+    std::string GetStringValue() const {
+        return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
+    }
+};
+static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
+
+struct MacAddress {
+    std::array<u8, 6> raw{};
+
+    friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
+};
+static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size");
+
+struct ScanFilter {
+    NetworkId network_id;
+    NetworkType network_type;
+    MacAddress mac_address;
+    Ssid ssid;
+    INSERT_PADDING_BYTES(0x10);
+    ScanFilterFlag flag;
+};
+static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size");
+
+struct CommonNetworkInfo {
+    MacAddress bssid;
+    Ssid ssid;
+    WifiChannel channel;
+    LinkLevel link_level;
+    PackedNetworkType network_type;
+    INSERT_PADDING_BYTES(0x4);
+};
+static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
+
+struct NodeInfo {
+    Ipv4Address ipv4_address;
+    MacAddress mac_address;
+    s8 node_id;
+    u8 is_connected;
+    std::array<u8, UserNameBytesMax + 1> user_name;
+    INSERT_PADDING_BYTES(0x1); // Reserved
+    s16 local_communication_version;
+    INSERT_PADDING_BYTES(0x10); // Reserved
+};
+static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
+
+struct LdnNetworkInfo {
+    std::array<u8, 0x10> security_parameter;
+    SecurityMode security_mode;
+    AcceptPolicy station_accept_policy;
+    u8 has_action_frame;
+    INSERT_PADDING_BYTES(0x2); // Padding
+    u8 node_count_max;
+    u8 node_count;
+    std::array<NodeInfo, NodeCountMax> nodes;
+    INSERT_PADDING_BYTES(0x2); // Reserved
+    u16 advertise_data_size;
+    std::array<u8, AdvertiseDataSizeMax> advertise_data;
+    INSERT_PADDING_BYTES(0x8C); // Reserved
+    u64 random_authentication_id;
+};
+static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
+
+struct NetworkInfo {
+    NetworkId network_id;
+    CommonNetworkInfo common;
+    LdnNetworkInfo ldn;
+};
+static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
+
+struct SecurityConfig {
+    SecurityMode security_mode;
+    u16 passphrase_size;
+    std::array<u8, PassphraseLengthMax> passphrase;
+};
+static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size");
+
+struct UserConfig {
+    std::array<u8, UserNameBytesMax + 1> user_name;
+    INSERT_PADDING_BYTES(0xF); // Reserved
+};
+static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size");
+
+#pragma pack(push, 4)
+struct ConnectRequest {
+    SecurityConfig security_config;
+    UserConfig user_config;
+    u32 local_communication_version;
+    u32 option_unknown;
+    NetworkInfo network_info;
+};
+static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size");
+#pragma pack(pop)
+
+struct SecurityParameter {
+    std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig
+    SessionId session_id;
+};
+static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size");
+
+struct NetworkConfig {
+    IntentId intent_id;
+    WifiChannel channel;
+    u8 node_count_max;
+    INSERT_PADDING_BYTES(0x1); // Reserved
+    u16 local_communication_version;
+    INSERT_PADDING_BYTES(0xA); // Reserved
+};
+static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size");
+
+struct AddressEntry {
+    Ipv4Address ipv4_address;
+    MacAddress mac_address;
+    INSERT_PADDING_BYTES(0x2); // Reserved
+};
+static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size");
+
+struct AddressList {
+    std::array<AddressEntry, 0x8> addresses;
+};
+static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
+
+} // namespace Service::LDN

From 8eb2c73381c2ed35767b51fde4102ec31d5ab5a1 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Mon, 8 Aug 2022 12:49:48 -0500
Subject: [PATCH 2/3] core: ldn: Address review comments

---
 src/core/hle/service/ldn/ldn.cpp       | 86 ++++++++++++++------------
 src/core/hle/service/ldn/ldn.h         |  1 -
 src/core/hle/service/ldn/ldn_results.h |  5 +-
 src/core/hle/service/ldn/ldn_types.h   | 20 +-----
 4 files changed, 51 insertions(+), 61 deletions(-)

diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index c8e1898f4..ff4169f8e 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -8,6 +8,7 @@
 #include "core/internal_network/network.h"
 #include "core/internal_network/network_interface.h"
 
+// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
 #undef CreateEvent
 
 namespace Service::LDN {
@@ -168,7 +169,7 @@ void IUserLocalCommunicationService::GetNetworkInfo(Kernel::HLERequestContext& c
         return;
     }
 
-    NetworkInfo networkInfo{};
+    NetworkInfo network_info{};
     const auto rc = ResultSuccess;
     if (rc.IsError()) {
         LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
@@ -178,9 +179,9 @@ void IUserLocalCommunicationService::GetNetworkInfo(Kernel::HLERequestContext& c
     }
 
     LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
-                networkInfo.common.ssid.GetStringValue(), networkInfo.ldn.node_count);
+                network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
 
-    ctx.WriteBuffer<NetworkInfo>(networkInfo);
+    ctx.WriteBuffer<NetworkInfo>(network_info);
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(rc);
 }
@@ -267,8 +268,7 @@ void IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(Kernel::HLEReque
     }
 
     NetworkInfo info;
-    std::vector<NodeLatestUpdate> latest_update{};
-    latest_update.resize(node_buffer_count);
+    std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
 
     const auto rc = ResultSuccess;
     if (rc.IsError()) {
@@ -311,14 +311,13 @@ void IUserLocalCommunicationService::ScanImpl(Kernel::HLERequestContext& ctx, bo
     }
 
     u16 count = 0;
-    std::vector<NetworkInfo> networks_info{};
-    networks_info.resize(network_info_size);
+    std::vector<NetworkInfo> network_infos(network_info_size);
 
     LOG_WARNING(Service_LDN,
                 "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
                 channel, scan_filter.flag, scan_filter.network_type);
 
-    ctx.WriteBuffer(networks_info);
+    ctx.WriteBuffer(network_infos);
 
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(ResultSuccess);
@@ -340,31 +339,39 @@ void IUserLocalCommunicationService::CloseAccessPoint(Kernel::HLERequestContext&
 }
 
 void IUserLocalCommunicationService::CreateNetwork(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    CreateNetworkImpl(ctx, false);
-}
-
-void IUserLocalCommunicationService::CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    CreateNetworkImpl(ctx, true);
-}
-
-void IUserLocalCommunicationService::CreateNetworkImpl(Kernel::HLERequestContext& ctx,
-                                                       bool is_private) {
     IPC::RequestParser rp{ctx};
+    struct Parameters {
+        SecurityConfig security_config;
+        UserConfig user_config;
+        INSERT_PADDING_WORDS_NOINIT(1);
+        NetworkConfig network_config;
+    };
+    static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
 
-    const auto security_config{rp.PopRaw<SecurityConfig>()};
-    [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>()
-                                                              : SecurityParameter{}};
-    const auto user_config{rp.PopRaw<UserConfig>()};
-    rp.Pop<u32>(); // Padding
-    const auto network_Config{rp.PopRaw<NetworkConfig>()};
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
 }
+
+void IUserLocalCommunicationService::CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    struct Parameters {
+        SecurityConfig security_config;
+        SecurityParameter security_parameter;
+        UserConfig user_config;
+        NetworkConfig network_config;
+    };
+    static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
+
+    const auto parameters{rp.PopRaw<Parameters>()};
+
+    LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
 void IUserLocalCommunicationService::DestroyNetwork(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_LDN, "(STUBBED) called");
 
@@ -413,14 +420,18 @@ void IUserLocalCommunicationService::Connect(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_LDN, "(STUBBED) called");
 
     IPC::RequestParser rp{ctx};
+    struct Parameters {
+        SecurityConfig security_config;
+        UserConfig user_config;
+        u32 local_communication_version;
+        u32 option;
+    };
+    static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
 
-    [[maybe_unused]] const auto securityConfig{rp.PopRaw<SecurityConfig>()};
-    const auto user_config{rp.PopRaw<UserConfig>()};
-    const auto local_communication_version{rp.Pop<u32>()};
-    [[maybe_unused]] const auto option{rp.Pop<u32>()};
+    const auto parameters{rp.PopRaw<Parameters>()};
 
-    std::vector<u8> read_buffer = ctx.ReadBuffer();
-    NetworkInfo networkInfo{};
+    const std::vector<u8> read_buffer = ctx.ReadBuffer();
+    NetworkInfo network_info{};
 
     if (read_buffer.size() != sizeof(NetworkInfo)) {
         LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
@@ -429,7 +440,7 @@ void IUserLocalCommunicationService::Connect(Kernel::HLERequestContext& ctx) {
         return;
     }
 
-    std::memcpy(&networkInfo, read_buffer.data(), read_buffer.size());
+    std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -445,9 +456,6 @@ void IUserLocalCommunicationService::Initialize(Kernel::HLERequestContext& ctx)
     LOG_WARNING(Service_LDN, "(STUBBED) called");
 
     const auto rc = InitializeImpl(ctx);
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
-    }
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(rc);
@@ -466,9 +474,6 @@ void IUserLocalCommunicationService::Initialize2(Kernel::HLERequestContext& ctx)
     LOG_WARNING(Service_LDN, "(STUBBED) called");
 
     const auto rc = InitializeImpl(ctx);
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
-    }
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(rc);
@@ -477,6 +482,7 @@ void IUserLocalCommunicationService::Initialize2(Kernel::HLERequestContext& ctx)
 Result IUserLocalCommunicationService::InitializeImpl(Kernel::HLERequestContext& ctx) {
     const auto network_interface = Network::GetSelectedNetworkInterface();
     if (!network_interface) {
+        LOG_ERROR(Service_LDN, "No network interface is set");
         return ResultAirplaneModeEnabled;
     }
 
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index 331455e3f..4ab8f7a9b 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -54,7 +54,6 @@ public:
 
     void CreateNetwork(Kernel::HLERequestContext& ctx);
     void CreateNetworkPrivate(Kernel::HLERequestContext& ctx);
-    void CreateNetworkImpl(Kernel::HLERequestContext& ctx, bool is_private);
 
     void DestroyNetwork(Kernel::HLERequestContext& ctx);
 
diff --git a/src/core/hle/service/ldn/ldn_results.h b/src/core/hle/service/ldn/ldn_results.h
index 8b6b436b7..f340bda42 100644
--- a/src/core/hle/service/ldn/ldn_results.h
+++ b/src/core/hle/service/ldn/ldn_results.h
@@ -1,6 +1,5 @@
-// Copyright 2022 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
 
 #pragma once
 
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
index 1132b2eb6..0c07a7397 100644
--- a/src/core/hle/service/ldn/ldn_types.h
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -1,6 +1,5 @@
-// Copyright 2022 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
 
 #pragma once
 
@@ -32,14 +31,6 @@ enum class NodeStateChange : u8 {
     DisconnectAndConnect,
 };
 
-inline NodeStateChange operator|(NodeStateChange a, NodeStateChange b) {
-    return static_cast<NodeStateChange>(static_cast<u8>(a) | static_cast<u8>(b));
-}
-
-inline NodeStateChange operator|=(NodeStateChange& a, NodeStateChange b) {
-    return a = a | b;
-}
-
 enum class ScanFilterFlag : u32 {
     None = 0,
     LocalCommunicationId = 1 << 0,
@@ -135,10 +126,7 @@ struct SessionId {
     u64 high;
     u64 low;
 
-public:
-    bool operator==(const SessionId& b) const {
-        return (low == b.low) && (high == b.high);
-    }
+    bool operator==(const SessionId&) const = default;
 };
 static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
 
@@ -160,7 +148,6 @@ struct Ssid {
     u8 length;
     std::array<char, SsidLengthMax + 1> raw;
 
-public:
     std::string GetStringValue() const {
         return std::string(raw.data(), length);
     }
@@ -173,7 +160,6 @@ struct Ipv4Address {
         std::array<u8, 4> bytes;
     };
 
-public:
     std::string GetStringValue() const {
         return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
     }

From 56115f7732e2b03b8122c10b3c3f69edb6ed7baa Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 11 Aug 2022 23:12:32 -0500
Subject: [PATCH 3/3] core: ldn: Address review comments part 2

---
 src/core/hle/service/ldn/ldn.cpp | 691 ++++++++++++++++---------------
 src/core/hle/service/ldn/ldn.h   |  66 ---
 2 files changed, 360 insertions(+), 397 deletions(-)

diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index ff4169f8e..c11daff54 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -5,6 +5,8 @@
 
 #include "core/core.h"
 #include "core/hle/service/ldn/ldn.h"
+#include "core/hle/service/ldn/ldn_results.h"
+#include "core/hle/service/ldn/ldn_types.h"
 #include "core/internal_network/network.h"
 #include "core/internal_network/network_interface.h"
 
@@ -98,11 +100,14 @@ public:
     }
 };
 
-IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
-    : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
-      service_context{system, "IUserLocalCommunicationService"}, room_network{
-                                                                     system_.GetRoomNetwork()} {
-    // clang-format off
+class IUserLocalCommunicationService final
+    : public ServiceFramework<IUserLocalCommunicationService> {
+public:
+    explicit IUserLocalCommunicationService(Core::System& system_)
+        : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
+          service_context{system, "IUserLocalCommunicationService"}, room_network{
+                                                                         system_.GetRoomNetwork()} {
+        // clang-format off
         static const FunctionInfo functions[] = {
             {0, &IUserLocalCommunicationService::GetState, "GetState"},
             {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
@@ -134,362 +139,386 @@ IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& sys
             {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
             {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
         };
-    // clang-format on
+        // clang-format on
 
-    RegisterHandlers(functions);
+        RegisterHandlers(functions);
 
-    state_change_event =
-        service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
-}
-
-IUserLocalCommunicationService::~IUserLocalCommunicationService() {
-    service_context.CloseEvent(state_change_event);
-}
-
-void IUserLocalCommunicationService::OnEventFired() {
-    state_change_event->GetWritableEvent().Signal();
-}
-
-void IUserLocalCommunicationService::GetState(Kernel::HLERequestContext& ctx) {
-    State state = State::Error;
-    LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.PushEnum(state);
-}
-
-void IUserLocalCommunicationService::GetNetworkInfo(Kernel::HLERequestContext& ctx) {
-    const auto write_buffer_size = ctx.GetWriteBufferSize();
-
-    if (write_buffer_size != sizeof(NetworkInfo)) {
-        LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultBadInput);
-        return;
+        state_change_event =
+            service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
     }
 
-    NetworkInfo network_info{};
-    const auto rc = ResultSuccess;
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+    ~IUserLocalCommunicationService() {
+        service_context.CloseEvent(state_change_event);
+    }
+
+    void OnEventFired() {
+        state_change_event->GetWritableEvent().Signal();
+    }
+
+    void GetState(Kernel::HLERequestContext& ctx) {
+        State state = State::Error;
+        LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(ResultSuccess);
+        rb.PushEnum(state);
+    }
+
+    void GetNetworkInfo(Kernel::HLERequestContext& ctx) {
+        const auto write_buffer_size = ctx.GetWriteBufferSize();
+
+        if (write_buffer_size != sizeof(NetworkInfo)) {
+            LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ResultBadInput);
+            return;
+        }
+
+        NetworkInfo network_info{};
+        const auto rc = ResultSuccess;
+        if (rc.IsError()) {
+            LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(rc);
+            return;
+        }
+
+        LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
+                    network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
+
+        ctx.WriteBuffer<NetworkInfo>(network_info);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(rc);
-        return;
     }
 
-    LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
-                network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
+    void GetDisconnectReason(Kernel::HLERequestContext& ctx) {
+        const auto disconnect_reason = DisconnectReason::None;
 
-    ctx.WriteBuffer<NetworkInfo>(network_info);
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(rc);
-}
+        LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
 
-void IUserLocalCommunicationService::GetDisconnectReason(Kernel::HLERequestContext& ctx) {
-    const auto disconnect_reason = DisconnectReason::None;
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(ResultSuccess);
+        rb.PushEnum(disconnect_reason);
+    }
 
-    LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
+    void GetSecurityParameter(Kernel::HLERequestContext& ctx) {
+        SecurityParameter security_parameter{};
+        NetworkInfo info{};
+        const Result rc = ResultSuccess;
 
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.PushEnum(disconnect_reason);
-}
+        if (rc.IsError()) {
+            LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(rc);
+            return;
+        }
 
-void IUserLocalCommunicationService::GetSecurityParameter(Kernel::HLERequestContext& ctx) {
-    SecurityParameter security_parameter;
-    NetworkInfo info;
-    const Result rc = ResultSuccess;
+        security_parameter.session_id = info.network_id.session_id;
+        std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
+                    sizeof(SecurityParameter::data));
+
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 10};
+        rb.Push(rc);
+        rb.PushRaw<SecurityParameter>(security_parameter);
+    }
+
+    void GetNetworkConfig(Kernel::HLERequestContext& ctx) {
+        NetworkConfig config{};
+        NetworkInfo info{};
+        const Result rc = ResultSuccess;
+
+        if (rc.IsError()) {
+            LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(rc);
+            return;
+        }
+
+        config.intent_id = info.network_id.intent_id;
+        config.channel = info.common.channel;
+        config.node_count_max = info.ldn.node_count_max;
+        config.local_communication_version = info.ldn.nodes[0].local_communication_version;
+
+        LOG_WARNING(Service_LDN,
+                    "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
+                    "local_communication_version={}",
+                    config.intent_id.local_communication_id, config.intent_id.scene_id,
+                    config.channel, config.node_count_max, config.local_communication_version);
+
+        IPC::ResponseBuilder rb{ctx, 10};
+        rb.Push(rc);
+        rb.PushRaw<NetworkConfig>(config);
+    }
+
+    void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
+        LOG_INFO(Service_LDN, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 1};
+        rb.Push(ResultSuccess);
+        rb.PushCopyObjects(state_change_event->GetReadableEvent());
+    }
+
+    void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
+        const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
+        const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
+
+        if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
+            LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
+                      node_buffer_count);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ResultBadInput);
+            return;
+        }
+
+        NetworkInfo info;
+        std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
+
+        const auto rc = ResultSuccess;
+        if (rc.IsError()) {
+            LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(rc);
+            return;
+        }
+
+        LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
+                    info.common.ssid.GetStringValue(), info.ldn.node_count);
+
+        ctx.WriteBuffer(info, 0);
+        ctx.WriteBuffer(latest_update, 1);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void Scan(Kernel::HLERequestContext& ctx) {
+        ScanImpl(ctx);
+    }
+
+    void ScanPrivate(Kernel::HLERequestContext& ctx) {
+        ScanImpl(ctx, true);
+    }
+
+    void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
+        IPC::RequestParser rp{ctx};
+        const auto channel{rp.PopEnum<WifiChannel>()};
+        const auto scan_filter{rp.PopRaw<ScanFilter>()};
+
+        const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
+
+        if (network_info_size == 0) {
+            LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ResultBadInput);
+            return;
+        }
+
+        u16 count = 0;
+        std::vector<NetworkInfo> network_infos(network_info_size);
+
+        LOG_WARNING(Service_LDN,
+                    "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
+                    channel, scan_filter.flag, scan_filter.network_type);
+
+        ctx.WriteBuffer(network_infos);
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(ResultSuccess);
+        rb.Push<u32>(count);
+    }
+
+    void OpenAccessPoint(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void CloseAccessPoint(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void CreateNetwork(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        struct Parameters {
+            SecurityConfig security_config;
+            UserConfig user_config;
+            INSERT_PADDING_WORDS_NOINIT(1);
+            NetworkConfig network_config;
+        };
+        static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
+
+        const auto parameters{rp.PopRaw<Parameters>()};
+
+        LOG_WARNING(Service_LDN,
+                    "(STUBBED) called, passphrase_size={}, security_mode={}, "
+                    "local_communication_version={}",
+                    parameters.security_config.passphrase_size,
+                    parameters.security_config.security_mode,
+                    parameters.network_config.local_communication_version);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        struct Parameters {
+            SecurityConfig security_config;
+            SecurityParameter security_parameter;
+            UserConfig user_config;
+            NetworkConfig network_config;
+        };
+        static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
+
+        const auto parameters{rp.PopRaw<Parameters>()};
+
+        LOG_WARNING(Service_LDN,
+                    "(STUBBED) called, passphrase_size={}, security_mode={}, "
+                    "local_communication_version={}",
+                    parameters.security_config.passphrase_size,
+                    parameters.security_config.security_mode,
+                    parameters.network_config.local_communication_version);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void DestroyNetwork(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
+        std::vector<u8> read_buffer = ctx.ReadBuffer();
+
+        LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void OpenStation(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void CloseStation(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void Connect(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        struct Parameters {
+            SecurityConfig security_config;
+            UserConfig user_config;
+            u32 local_communication_version;
+            u32 option;
+        };
+        static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
+
+        const auto parameters{rp.PopRaw<Parameters>()};
+
+        LOG_WARNING(Service_LDN,
+                    "(STUBBED) called, passphrase_size={}, security_mode={}, "
+                    "local_communication_version={}",
+                    parameters.security_config.passphrase_size,
+                    parameters.security_config.security_mode,
+                    parameters.local_communication_version);
+
+        const std::vector<u8> read_buffer = ctx.ReadBuffer();
+        NetworkInfo network_info{};
+
+        if (read_buffer.size() != sizeof(NetworkInfo)) {
+            LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ResultBadInput);
+            return;
+        }
+
+        std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+
+    void Disconnect(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
+    void Initialize(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        const auto rc = InitializeImpl(ctx);
 
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(rc);
-        return;
     }
 
-    security_parameter.session_id = info.network_id.session_id;
-    std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
-                sizeof(SecurityParameter::data));
+    void Finalize(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
 
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
+        is_initialized = false;
 
-    IPC::ResponseBuilder rb{ctx, 10};
-    rb.Push(rc);
-    rb.PushRaw<SecurityParameter>(security_parameter);
-}
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultSuccess);
+    }
 
-void IUserLocalCommunicationService::GetNetworkConfig(Kernel::HLERequestContext& ctx) {
-    NetworkConfig config;
-    NetworkInfo info;
-    const Result rc = ResultSuccess;
+    void Initialize2(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+        const auto rc = InitializeImpl(ctx);
 
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(rc);
-        return;
     }
 
-    config.intent_id = info.network_id.intent_id;
-    config.channel = info.common.channel;
-    config.node_count_max = info.ldn.node_count_max;
-    config.local_communication_version = info.ldn.nodes[0].local_communication_version;
+    Result InitializeImpl(Kernel::HLERequestContext& ctx) {
+        const auto network_interface = Network::GetSelectedNetworkInterface();
+        if (!network_interface) {
+            LOG_ERROR(Service_LDN, "No network interface is set");
+            return ResultAirplaneModeEnabled;
+        }
 
-    LOG_WARNING(Service_LDN,
-                "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
-                "local_communication_version={}",
-                config.intent_id.local_communication_id, config.intent_id.scene_id, config.channel,
-                config.node_count_max, config.local_communication_version);
-
-    IPC::ResponseBuilder rb{ctx, 10};
-    rb.Push(rc);
-    rb.PushRaw<NetworkConfig>(config);
-}
-
-void IUserLocalCommunicationService::AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
-    LOG_INFO(Service_LDN, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(state_change_event->GetReadableEvent());
-}
-
-void IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
-    const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
-    const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
-
-    if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
-        LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
-                  node_buffer_count);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultBadInput);
-        return;
-    }
-
-    NetworkInfo info;
-    std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
-
-    const auto rc = ResultSuccess;
-    if (rc.IsError()) {
-        LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(rc);
-        return;
-    }
-
-    LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
-                info.common.ssid.GetStringValue(), info.ldn.node_count);
-
-    ctx.WriteBuffer(info, 0);
-    ctx.WriteBuffer(latest_update, 1);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::Scan(Kernel::HLERequestContext& ctx) {
-    ScanImpl(ctx);
-}
-
-void IUserLocalCommunicationService::ScanPrivate(Kernel::HLERequestContext& ctx) {
-    ScanImpl(ctx, true);
-}
-
-void IUserLocalCommunicationService::ScanImpl(Kernel::HLERequestContext& ctx, bool is_private) {
-    IPC::RequestParser rp{ctx};
-    const auto channel{rp.PopEnum<WifiChannel>()};
-    const auto scan_filter{rp.PopRaw<ScanFilter>()};
-
-    const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
-
-    if (network_info_size == 0) {
-        LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultBadInput);
-        return;
-    }
-
-    u16 count = 0;
-    std::vector<NetworkInfo> network_infos(network_info_size);
-
-    LOG_WARNING(Service_LDN,
-                "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
-                channel, scan_filter.flag, scan_filter.network_type);
-
-    ctx.WriteBuffer(network_infos);
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u32>(count);
-}
-
-void IUserLocalCommunicationService::OpenAccessPoint(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::CloseAccessPoint(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::CreateNetwork(Kernel::HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    struct Parameters {
-        SecurityConfig security_config;
-        UserConfig user_config;
-        INSERT_PADDING_WORDS_NOINIT(1);
-        NetworkConfig network_config;
-    };
-    static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
-
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    struct Parameters {
-        SecurityConfig security_config;
-        SecurityParameter security_parameter;
-        UserConfig user_config;
-        NetworkConfig network_config;
-    };
-    static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
-
-    const auto parameters{rp.PopRaw<Parameters>()};
-
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::DestroyNetwork(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::SetAdvertiseData(Kernel::HLERequestContext& ctx) {
-    std::vector<u8> read_buffer = ctx.ReadBuffer();
-
-    LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::OpenStation(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::CloseStation(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::Connect(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::RequestParser rp{ctx};
-    struct Parameters {
-        SecurityConfig security_config;
-        UserConfig user_config;
-        u32 local_communication_version;
-        u32 option;
-    };
-    static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
-
-    const auto parameters{rp.PopRaw<Parameters>()};
-
-    const std::vector<u8> read_buffer = ctx.ReadBuffer();
-    NetworkInfo network_info{};
-
-    if (read_buffer.size() != sizeof(NetworkInfo)) {
-        LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultBadInput);
-        return;
-    }
-
-    std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::Disconnect(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-void IUserLocalCommunicationService::Initialize(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    const auto rc = InitializeImpl(ctx);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(rc);
-}
-
-void IUserLocalCommunicationService::Finalize(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    is_initialized = false;
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IUserLocalCommunicationService::Initialize2(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_LDN, "(STUBBED) called");
-
-    const auto rc = InitializeImpl(ctx);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(rc);
-}
-
-Result IUserLocalCommunicationService::InitializeImpl(Kernel::HLERequestContext& ctx) {
-    const auto network_interface = Network::GetSelectedNetworkInterface();
-    if (!network_interface) {
-        LOG_ERROR(Service_LDN, "No network interface is set");
+        is_initialized = true;
+        // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
         return ResultAirplaneModeEnabled;
     }
 
-    is_initialized = true;
-    // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
-    return ResultAirplaneModeEnabled;
-}
+    KernelHelpers::ServiceContext service_context;
+    Kernel::KEvent* state_change_event;
+    Network::RoomNetwork& room_network;
+
+    bool is_initialized{};
+};
 
 class LDNS final : public ServiceFramework<LDNS> {
 public:
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index 4ab8f7a9b..6afe2ea6f 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -7,8 +7,6 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/result.h"
 #include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/ldn/ldn_results.h"
-#include "core/hle/service/ldn/ldn_types.h"
 #include "core/hle/service/sm/sm.h"
 
 namespace Core {
@@ -24,68 +22,4 @@ namespace Service::LDN {
 /// Registers all LDN services with the specified service manager.
 void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
 
-class IUserLocalCommunicationService final
-    : public ServiceFramework<IUserLocalCommunicationService> {
-public:
-    explicit IUserLocalCommunicationService(Core::System& system_);
-    ~IUserLocalCommunicationService() override;
-
-    void GetState(Kernel::HLERequestContext& ctx);
-
-    void GetNetworkInfo(Kernel::HLERequestContext& ctx);
-
-    void GetDisconnectReason(Kernel::HLERequestContext& ctx);
-
-    void GetSecurityParameter(Kernel::HLERequestContext& ctx);
-
-    void GetNetworkConfig(Kernel::HLERequestContext& ctx);
-
-    void AttachStateChangeEvent(Kernel::HLERequestContext& ctx);
-
-    void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx);
-
-    void Scan(Kernel::HLERequestContext& ctx);
-    void ScanPrivate(Kernel::HLERequestContext& ctx);
-    void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false);
-
-    void OpenAccessPoint(Kernel::HLERequestContext& ctx);
-
-    void CloseAccessPoint(Kernel::HLERequestContext& ctx);
-
-    void CreateNetwork(Kernel::HLERequestContext& ctx);
-    void CreateNetworkPrivate(Kernel::HLERequestContext& ctx);
-
-    void DestroyNetwork(Kernel::HLERequestContext& ctx);
-
-    void SetAdvertiseData(Kernel::HLERequestContext& ctx);
-
-    void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx);
-
-    void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx);
-
-    void OpenStation(Kernel::HLERequestContext& ctx);
-
-    void CloseStation(Kernel::HLERequestContext& ctx);
-
-    void Disconnect(Kernel::HLERequestContext& ctx);
-
-    void Connect(Kernel::HLERequestContext& ctx);
-
-    void Initialize(Kernel::HLERequestContext& ctx);
-
-    void Finalize(Kernel::HLERequestContext& ctx);
-
-    void Initialize2(Kernel::HLERequestContext& ctx);
-    Result InitializeImpl(Kernel::HLERequestContext& ctx);
-
-private:
-    void OnEventFired();
-
-    KernelHelpers::ServiceContext service_context;
-    Kernel::KEvent* state_change_event;
-    Network::RoomNetwork& room_network;
-
-    bool is_initialized{};
-};
-
 } // namespace Service::LDN