mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	service: ldn: Migrate and refractor service to new IPC
This commit is contained in:
		@@ -668,6 +668,18 @@ add_library(core STATIC
 | 
			
		||||
    hle/service/ldn/ldn.h
 | 
			
		||||
    hle/service/ldn/ldn_results.h
 | 
			
		||||
    hle/service/ldn/ldn_types.h
 | 
			
		||||
    hle/service/ldn/monitor_service.cpp
 | 
			
		||||
    hle/service/ldn/monitor_service.h
 | 
			
		||||
    hle/service/ldn/sf_monitor_service.cpp
 | 
			
		||||
    hle/service/ldn/sf_monitor_service.h
 | 
			
		||||
    hle/service/ldn/sf_service.cpp
 | 
			
		||||
    hle/service/ldn/sf_service.h
 | 
			
		||||
    hle/service/ldn/sf_service_monitor.cpp
 | 
			
		||||
    hle/service/ldn/sf_service_monitor.h
 | 
			
		||||
    hle/service/ldn/system_local_communication_service.cpp
 | 
			
		||||
    hle/service/ldn/system_local_communication_service.h
 | 
			
		||||
    hle/service/ldn/user_local_communication_service.cpp
 | 
			
		||||
    hle/service/ldn/user_local_communication_service.h
 | 
			
		||||
    hle/service/ldr/ldr.cpp
 | 
			
		||||
    hle/service/ldr/ldr.h
 | 
			
		||||
    hle/service/lm/lm.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -85,15 +85,14 @@ Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network) const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network,
 | 
			
		||||
                                    std::vector<NodeLatestUpdate>& out_updates,
 | 
			
		||||
                                    std::size_t buffer_count) {
 | 
			
		||||
    if (buffer_count > NodeCountMax) {
 | 
			
		||||
                                    std::span<NodeLatestUpdate> out_updates) {
 | 
			
		||||
    if (out_updates.size() > NodeCountMax) {
 | 
			
		||||
        return ResultInvalidBufferCount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (state == State::AccessPointCreated || state == State::StationConnected) {
 | 
			
		||||
        std::memcpy(&out_network, &network_info, sizeof(network_info));
 | 
			
		||||
        for (std::size_t i = 0; i < buffer_count; i++) {
 | 
			
		||||
        for (std::size_t i = 0; i < out_updates.size(); i++) {
 | 
			
		||||
            out_updates[i].state_change = node_changes[i].state_change;
 | 
			
		||||
            node_changes[i].state_change = NodeStateChange::None;
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,15 +106,8 @@ DisconnectReason LANDiscovery::GetDisconnectReason() const {
 | 
			
		||||
    return disconnect_reason;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
 | 
			
		||||
Result LANDiscovery::Scan(std::span<NetworkInfo> out_networks, s16& out_count,
 | 
			
		||||
                          const ScanFilter& filter) {
 | 
			
		||||
    if (!IsFlagSet(filter.flag, ScanFilterFlag::NetworkType) ||
 | 
			
		||||
        filter.network_type <= NetworkType::All) {
 | 
			
		||||
        if (!IsFlagSet(filter.flag, ScanFilterFlag::Ssid) && filter.ssid.length >= SsidLengthMax) {
 | 
			
		||||
            return ResultBadInput;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        std::scoped_lock lock{packet_mutex};
 | 
			
		||||
        scan_results.clear();
 | 
			
		||||
@@ -128,7 +120,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
 | 
			
		||||
 | 
			
		||||
    std::scoped_lock lock{packet_mutex};
 | 
			
		||||
    for (const auto& [key, info] : scan_results) {
 | 
			
		||||
        if (count >= networks.size()) {
 | 
			
		||||
        if (out_count >= static_cast<s16>(out_networks.size())) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -159,7 +151,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        networks[count++] = info;
 | 
			
		||||
        out_networks[out_count++] = info;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
 
 | 
			
		||||
@@ -54,11 +54,10 @@ public:
 | 
			
		||||
    void SetState(State new_state);
 | 
			
		||||
 | 
			
		||||
    Result GetNetworkInfo(NetworkInfo& out_network) const;
 | 
			
		||||
    Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates,
 | 
			
		||||
                          std::size_t buffer_count);
 | 
			
		||||
    Result GetNetworkInfo(NetworkInfo& out_network, std::span<NodeLatestUpdate> out_updates);
 | 
			
		||||
 | 
			
		||||
    DisconnectReason GetDisconnectReason() const;
 | 
			
		||||
    Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter);
 | 
			
		||||
    Result Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter);
 | 
			
		||||
    Result SetAdvertiseData(std::span<const u8> data);
 | 
			
		||||
 | 
			
		||||
    Result OpenAccessPoint();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,24 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/hle/service/ldn/lan_discovery.h"
 | 
			
		||||
#include "core/hle/service/cmif_serialization.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/hle/service/server_manager.h"
 | 
			
		||||
#include "core/internal_network/network.h"
 | 
			
		||||
#include "core/internal_network/network_interface.h"
 | 
			
		||||
#include "network/network.h"
 | 
			
		||||
 | 
			
		||||
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
 | 
			
		||||
#undef CreateEvent
 | 
			
		||||
#include "core/hle/service/ldn/monitor_service.h"
 | 
			
		||||
#include "core/hle/service/ldn/sf_monitor_service.h"
 | 
			
		||||
#include "core/hle/service/ldn/sf_service.h"
 | 
			
		||||
#include "core/hle/service/ldn/sf_service_monitor.h"
 | 
			
		||||
#include "core/hle/service/ldn/system_local_communication_service.h"
 | 
			
		||||
#include "core/hle/service/ldn/user_local_communication_service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
class IMonitorService final : public ServiceFramework<IMonitorService> {
 | 
			
		||||
class IMonitorServiceCreator final : public ServiceFramework<IMonitorServiceCreator> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} {
 | 
			
		||||
    explicit IMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"},
 | 
			
		||||
            {1, nullptr, "GetNetworkInfoForMonitor"},
 | 
			
		||||
            {2, nullptr, "GetIpv4AddressForMonitor"},
 | 
			
		||||
            {3, nullptr, "GetDisconnectReasonForMonitor"},
 | 
			
		||||
            {4, nullptr, "GetSecurityParameterForMonitor"},
 | 
			
		||||
            {5, nullptr, "GetNetworkConfigForMonitor"},
 | 
			
		||||
            {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"},
 | 
			
		||||
            {101, nullptr, "FinalizeMonitor"},
 | 
			
		||||
            {0, C<&IMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"}
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
@@ -38,84 +26,20 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void GetStateForMonitor(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushEnum(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InitializeMonitor(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        state = State::Initialized;
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    State state{State::None};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LDNM final : public ServiceFramework<LDNM> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateMonitorService(HLERequestContext& ctx) {
 | 
			
		||||
    Result CreateMonitorService(OutInterface<IMonitorService> out_interface) {
 | 
			
		||||
        LOG_DEBUG(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<IMonitorService>(system);
 | 
			
		||||
        *out_interface = std::make_shared<IMonitorService>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ISystemLocalCommunicationService final
 | 
			
		||||
    : public ServiceFramework<ISystemLocalCommunicationService> {
 | 
			
		||||
class ISystemServiceCreator final : public ServiceFramework<ISystemServiceCreator> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISystemLocalCommunicationService(Core::System& system_)
 | 
			
		||||
        : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
 | 
			
		||||
    explicit ISystemServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, nullptr, "GetState"},
 | 
			
		||||
            {1, nullptr, "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"},
 | 
			
		||||
            {104, nullptr, "SetWirelessControllerRestriction"},
 | 
			
		||||
            {200, nullptr, "OpenAccessPoint"},
 | 
			
		||||
            {201, nullptr, "CloseAccessPoint"},
 | 
			
		||||
            {202, nullptr, "CreateNetwork"},
 | 
			
		||||
            {203, nullptr, "CreateNetworkPrivate"},
 | 
			
		||||
            {204, nullptr, "DestroyNetwork"},
 | 
			
		||||
            {205, nullptr, "Reject"},
 | 
			
		||||
            {206, nullptr, "SetAdvertiseData"},
 | 
			
		||||
            {207, nullptr, "SetStationAcceptPolicy"},
 | 
			
		||||
            {208, nullptr, "AddAcceptFilterEntry"},
 | 
			
		||||
            {209, nullptr, "ClearAcceptFilter"},
 | 
			
		||||
            {300, nullptr, "OpenStation"},
 | 
			
		||||
            {301, nullptr, "CloseStation"},
 | 
			
		||||
            {302, nullptr, "Connect"},
 | 
			
		||||
            {303, nullptr, "ConnectPrivate"},
 | 
			
		||||
            {304, nullptr, "Disconnect"},
 | 
			
		||||
            {400, nullptr, "InitializeSystem"},
 | 
			
		||||
            {401, nullptr, "FinalizeSystem"},
 | 
			
		||||
            {402, nullptr, "SetOperationMode"},
 | 
			
		||||
            {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"},
 | 
			
		||||
            {0, C<&ISystemServiceCreator::CreateSystemLocalCommunicationService>, "CreateSystemLocalCommunicationService"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
@@ -123,651 +47,78 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void InitializeSystem2(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IUserLocalCommunicationService final
 | 
			
		||||
    : public ServiceFramework<IUserLocalCommunicationService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IUserLocalCommunicationService(Core::System& system_)
 | 
			
		||||
        : ServiceFramework{system_, "IUserLocalCommunicationService"},
 | 
			
		||||
          service_context{system, "IUserLocalCommunicationService"},
 | 
			
		||||
          room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &IUserLocalCommunicationService::GetState, "GetState"},
 | 
			
		||||
            {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
 | 
			
		||||
            {2, &IUserLocalCommunicationService::GetIpv4Address, "GetIpv4Address"},
 | 
			
		||||
            {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, &IUserLocalCommunicationService::SetWirelessControllerRestriction, "SetWirelessControllerRestriction"},
 | 
			
		||||
            {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
 | 
			
		||||
            {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
 | 
			
		||||
            {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
 | 
			
		||||
            {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
 | 
			
		||||
            {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
 | 
			
		||||
            {205, nullptr, "Reject"},
 | 
			
		||||
            {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
 | 
			
		||||
            {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
 | 
			
		||||
            {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
 | 
			
		||||
            {209, nullptr, "ClearAcceptFilter"},
 | 
			
		||||
            {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
 | 
			
		||||
            {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
 | 
			
		||||
            {302, &IUserLocalCommunicationService::Connect, "Connect"},
 | 
			
		||||
            {303, nullptr, "ConnectPrivate"},
 | 
			
		||||
            {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
 | 
			
		||||
            {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
 | 
			
		||||
            {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
 | 
			
		||||
            {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
        state_change_event =
 | 
			
		||||
            service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~IUserLocalCommunicationService() {
 | 
			
		||||
        if (is_initialized) {
 | 
			
		||||
            if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
                room_member->Unbind(ldn_packet_received);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        service_context.CloseEvent(state_change_event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Callback to parse and handle a received LDN packet.
 | 
			
		||||
    void OnLDNPacketReceived(const Network::LDNPacket& packet) {
 | 
			
		||||
        lan_discovery.ReceivePacket(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void OnEventFired() {
 | 
			
		||||
        state_change_event->Signal();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetState(HLERequestContext& ctx) {
 | 
			
		||||
        State state = State::Error;
 | 
			
		||||
 | 
			
		||||
        if (is_initialized) {
 | 
			
		||||
            state = lan_discovery.GetState();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushEnum(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetNetworkInfo(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 = lan_discovery.GetNetworkInfo(network_info);
 | 
			
		||||
        if (rc.IsError()) {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(rc);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ctx.WriteBuffer<NetworkInfo>(network_info);
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetIpv4Address(HLERequestContext& ctx) {
 | 
			
		||||
        const auto network_interface = Network::GetSelectedNetworkInterface();
 | 
			
		||||
 | 
			
		||||
        if (!network_interface) {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "No network interface available");
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(ResultNoIpAddress);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ipv4Address current_address{Network::TranslateIPv4(network_interface->ip_address)};
 | 
			
		||||
        Ipv4Address subnet_mask{Network::TranslateIPv4(network_interface->subnet_mask)};
 | 
			
		||||
 | 
			
		||||
        // When we're connected to a room, spoof the hosts IP address
 | 
			
		||||
        if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
            if (room_member->IsConnected()) {
 | 
			
		||||
                current_address = room_member->GetFakeIpAddress();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::reverse(std::begin(current_address), std::end(current_address)); // ntohl
 | 
			
		||||
        std::reverse(std::begin(subnet_mask), std::end(subnet_mask));         // ntohl
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushRaw(current_address);
 | 
			
		||||
        rb.PushRaw(subnet_mask);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetDisconnectReason(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushEnum(lan_discovery.GetDisconnectReason());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetSecurityParameter(HLERequestContext& ctx) {
 | 
			
		||||
        SecurityParameter security_parameter{};
 | 
			
		||||
        NetworkInfo info{};
 | 
			
		||||
        const Result rc = lan_discovery.GetNetworkInfo(info);
 | 
			
		||||
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 10};
 | 
			
		||||
        rb.Push(rc);
 | 
			
		||||
        rb.PushRaw<SecurityParameter>(security_parameter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetNetworkConfig(HLERequestContext& ctx) {
 | 
			
		||||
        NetworkConfig config{};
 | 
			
		||||
        NetworkInfo info{};
 | 
			
		||||
        const Result rc = lan_discovery.GetNetworkInfo(info);
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 10};
 | 
			
		||||
        rb.Push(rc);
 | 
			
		||||
        rb.PushRaw<NetworkConfig>(config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AttachStateChangeEvent(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushCopyObjects(state_change_event->GetReadableEvent());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetNetworkInfoLatestUpdate(HLERequestContext& ctx) {
 | 
			
		||||
        const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
 | 
			
		||||
        const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1);
 | 
			
		||||
 | 
			
		||||
        if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", 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 = lan_discovery.GetNetworkInfo(info, latest_update, latest_update.size());
 | 
			
		||||
        if (rc.IsError()) {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(rc);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ctx.WriteBuffer(info, 0);
 | 
			
		||||
        ctx.WriteBuffer(latest_update, 1);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scan(HLERequestContext& ctx) {
 | 
			
		||||
        ScanImpl(ctx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ScanPrivate(HLERequestContext& ctx) {
 | 
			
		||||
        ScanImpl(ctx, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ScanImpl(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.GetWriteBufferNumElements<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);
 | 
			
		||||
        Result rc = lan_discovery.Scan(network_infos, count, scan_filter);
 | 
			
		||||
 | 
			
		||||
        LOG_INFO(Service_LDN,
 | 
			
		||||
                 "called, channel={}, filter_scan_flag={}, filter_network_type={}, is_private={}",
 | 
			
		||||
                 channel, scan_filter.flag, scan_filter.network_type, is_private);
 | 
			
		||||
 | 
			
		||||
        ctx.WriteBuffer(network_infos);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
        rb.Push(rc);
 | 
			
		||||
        rb.Push<u32>(count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetWirelessControllerRestriction(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void OpenAccessPoint(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.OpenAccessPoint());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CloseAccessPoint(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.CloseAccessPoint());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateNetwork(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        CreateNetworkImpl(ctx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateNetworkPrivate(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        CreateNetworkImpl(ctx, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateNetworkImpl(HLERequestContext& ctx, bool is_private = false) {
 | 
			
		||||
        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(lan_discovery.CreateNetwork(security_config, user_config, network_Config));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void DestroyNetwork(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.DestroyNetwork());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetAdvertiseData(HLERequestContext& ctx) {
 | 
			
		||||
        const auto read_buffer = ctx.ReadBuffer();
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetStationAcceptPolicy(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AddAcceptFilterEntry(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void OpenStation(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.OpenStation());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CloseStation(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.CloseStation());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Connect(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_INFO(Service_LDN,
 | 
			
		||||
                 "called, passphrase_size={}, security_mode={}, "
 | 
			
		||||
                 "local_communication_version={}",
 | 
			
		||||
                 parameters.security_config.passphrase_size,
 | 
			
		||||
                 parameters.security_config.security_mode, parameters.local_communication_version);
 | 
			
		||||
 | 
			
		||||
        const auto read_buffer = ctx.ReadBuffer();
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NetworkInfo network_info{};
 | 
			
		||||
        std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.Connect(network_info, parameters.user_config,
 | 
			
		||||
                                      static_cast<u16>(parameters.local_communication_version)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Disconnect(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.Disconnect());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Initialize(HLERequestContext& ctx) {
 | 
			
		||||
        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 Finalize(HLERequestContext& ctx) {
 | 
			
		||||
        if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
            room_member->Unbind(ldn_packet_received);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        is_initialized = false;
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(lan_discovery.Finalize());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Initialize2(HLERequestContext& ctx) {
 | 
			
		||||
        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 InitializeImpl(HLERequestContext& ctx) {
 | 
			
		||||
        const auto network_interface = Network::GetSelectedNetworkInterface();
 | 
			
		||||
        if (!network_interface) {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "No network interface is set");
 | 
			
		||||
            return ResultAirplaneModeEnabled;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
            ldn_packet_received = room_member->BindOnLdnPacketReceived(
 | 
			
		||||
                [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
 | 
			
		||||
        } else {
 | 
			
		||||
            LOG_ERROR(Service_LDN, "Couldn't bind callback!");
 | 
			
		||||
            return ResultAirplaneModeEnabled;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lan_discovery.Initialize([&]() { OnEventFired(); });
 | 
			
		||||
        is_initialized = true;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KernelHelpers::ServiceContext service_context;
 | 
			
		||||
    Kernel::KEvent* state_change_event;
 | 
			
		||||
    Network::RoomNetwork& room_network;
 | 
			
		||||
    LANDiscovery lan_discovery;
 | 
			
		||||
 | 
			
		||||
    // Callback identifier for the OnLDNPacketReceived event.
 | 
			
		||||
    Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
 | 
			
		||||
 | 
			
		||||
    bool is_initialized{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LDNS final : public ServiceFramework<LDNS> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateSystemLocalCommunicationService(HLERequestContext& ctx) {
 | 
			
		||||
    Result CreateSystemLocalCommunicationService(
 | 
			
		||||
        OutInterface<ISystemLocalCommunicationService> out_interface) {
 | 
			
		||||
        LOG_DEBUG(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<ISystemLocalCommunicationService>(system);
 | 
			
		||||
        *out_interface = std::make_shared<ISystemLocalCommunicationService>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LDNU final : public ServiceFramework<LDNU> {
 | 
			
		||||
class IUserServiceCreator final : public ServiceFramework<IUserServiceCreator> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
 | 
			
		||||
    explicit IUserServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
 | 
			
		||||
            {0, C<&IUserServiceCreator::CreateUserLocalCommunicationService>, "CreateUserLocalCommunicationService"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateUserLocalCommunicationService(HLERequestContext& ctx) {
 | 
			
		||||
private:
 | 
			
		||||
    Result CreateUserLocalCommunicationService(
 | 
			
		||||
        OutInterface<IUserLocalCommunicationService> out_interface) {
 | 
			
		||||
        LOG_DEBUG(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<IUserLocalCommunicationService>(system);
 | 
			
		||||
        *out_interface = std::make_shared<IUserLocalCommunicationService>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class INetworkService final : public ServiceFramework<INetworkService> {
 | 
			
		||||
class ISfServiceCreator final : public ServiceFramework<ISfServiceCreator> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} {
 | 
			
		||||
    explicit ISfServiceCreator(Core::System& system_, bool is_system_, const char* name_)
 | 
			
		||||
        : ServiceFramework{system_, name_}, is_system{is_system_} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, nullptr, "Initialize"},
 | 
			
		||||
            {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
 | 
			
		||||
            {264, nullptr, "GetNetworkInterfaceLastError"},
 | 
			
		||||
            {272, nullptr, "GetRole"},
 | 
			
		||||
            {280, nullptr, "GetAdvertiseData"},
 | 
			
		||||
            {288, nullptr, "GetGroupInfo"},
 | 
			
		||||
            {296, nullptr, "GetGroupInfo2"},
 | 
			
		||||
            {304, nullptr, "GetGroupOwner"},
 | 
			
		||||
            {312, nullptr, "GetIpConfig"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
            {512, nullptr, "Scan"},
 | 
			
		||||
            {768, nullptr, "CreateGroup"},
 | 
			
		||||
            {776, nullptr, "DestroyGroup"},
 | 
			
		||||
            {784, nullptr, "SetAdvertiseData"},
 | 
			
		||||
            {1536, nullptr, "SendToOtherGroup"},
 | 
			
		||||
            {1544, nullptr, "RecvFromOtherGroup"},
 | 
			
		||||
            {1552, nullptr, "AddAcceptableGroupId"},
 | 
			
		||||
            {1560, nullptr, "ClearAcceptableGroupId"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit INetworkServiceMonitor(Core::System& system_)
 | 
			
		||||
        : ServiceFramework{system_, "INetworkServiceMonitor"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &INetworkServiceMonitor::Initialize, "Initialize"},
 | 
			
		||||
            {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
 | 
			
		||||
            {264, nullptr, "GetNetworkInterfaceLastError"},
 | 
			
		||||
            {272, nullptr, "GetRole"},
 | 
			
		||||
            {280, nullptr, "GetAdvertiseData"},
 | 
			
		||||
            {281, nullptr, "GetAdvertiseData2"},
 | 
			
		||||
            {288, nullptr, "GetGroupInfo"},
 | 
			
		||||
            {296, nullptr, "GetGroupInfo2"},
 | 
			
		||||
            {304, nullptr, "GetGroupOwner"},
 | 
			
		||||
            {312, nullptr, "GetIpConfig"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
            {328, nullptr, "AttachJoinEvent"},
 | 
			
		||||
            {336, nullptr, "GetMembers"},
 | 
			
		||||
            {0, C<&ISfServiceCreator::CreateNetworkService>, "CreateNetworkService"},
 | 
			
		||||
            {8, C<&ISfServiceCreator::CreateNetworkServiceMonitor>, "CreateNetworkServiceMonitor"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Initialize(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultDisabled);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LP2PAPP final : public ServiceFramework<LP2PAPP> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"},
 | 
			
		||||
            {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateNetworkervice(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 reserved_input = rp.Pop<u64>();
 | 
			
		||||
        const u32 input = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result CreateNetworkService(OutInterface<ISfService> out_interface, u32 input,
 | 
			
		||||
                                u64 reserved_input) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
 | 
			
		||||
                    input);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<INetworkService>(system);
 | 
			
		||||
        *out_interface = std::make_shared<ISfService>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateMonitorService(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 reserved_input = rp.Pop<u64>();
 | 
			
		||||
 | 
			
		||||
    Result CreateNetworkServiceMonitor(OutInterface<ISfServiceMonitor> out_interface,
 | 
			
		||||
                                       u64 reserved_input) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<INetworkServiceMonitor>(system);
 | 
			
		||||
        *out_interface = std::make_shared<ISfServiceMonitor>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_system{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LP2PSYS final : public ServiceFramework<LP2PSYS> {
 | 
			
		||||
class ISfMonitorServiceCreator final : public ServiceFramework<ISfMonitorServiceCreator> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} {
 | 
			
		||||
    explicit ISfMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"},
 | 
			
		||||
            {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateNetworkervice(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 reserved_input = rp.Pop<u64>();
 | 
			
		||||
        const u32 input = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
 | 
			
		||||
                    input);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<INetworkService>(system);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateMonitorService(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 reserved_input = rp.Pop<u64>();
 | 
			
		||||
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<INetworkServiceMonitor>(system);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISfMonitorService(Core::System& system_)
 | 
			
		||||
        : ServiceFramework{system_, "ISfMonitorService"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &ISfMonitorService::Initialize, "Initialize"},
 | 
			
		||||
            {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
            {0, C<&ISfMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
@@ -775,64 +126,27 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void Initialize(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.Push(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetGroupInfo(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
        struct GroupInfo {
 | 
			
		||||
            std::array<u8, 0x200> info;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        GroupInfo group_info{};
 | 
			
		||||
 | 
			
		||||
        ctx.WriteBuffer(group_info);
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LP2PM final : public ServiceFramework<LP2PM> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &LP2PM::CreateMonitorService, "CreateMonitorService"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void CreateMonitorService(HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 reserved_input = rp.Pop<u64>();
 | 
			
		||||
 | 
			
		||||
    Result CreateMonitorService(OutInterface<ISfMonitorService> out_interface, u64 reserved_input) {
 | 
			
		||||
        LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
        rb.PushIpcInterface<ISfMonitorService>(system);
 | 
			
		||||
        *out_interface = std::make_shared<ISfMonitorService>(system);
 | 
			
		||||
        R_SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void LoopProcess(Core::System& system) {
 | 
			
		||||
    auto server_manager = std::make_unique<ServerManager>(system);
 | 
			
		||||
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:m", std::make_shared<IMonitorServiceCreator>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:s", std::make_shared<ISystemServiceCreator>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("ldn:u", std::make_shared<IUserServiceCreator>(system));
 | 
			
		||||
 | 
			
		||||
    server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system));
 | 
			
		||||
    server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system));
 | 
			
		||||
    server_manager->RegisterNamedService(
 | 
			
		||||
        "lp2p:app", std::make_shared<ISfServiceCreator>(system, false, "lp2p:app"));
 | 
			
		||||
    server_manager->RegisterNamedService(
 | 
			
		||||
        "lp2p:sys", std::make_shared<ISfServiceCreator>(system, true, "lp2p:sys"));
 | 
			
		||||
    server_manager->RegisterNamedService("lp2p:m",
 | 
			
		||||
                                         std::make_shared<ISfMonitorServiceCreator>(system));
 | 
			
		||||
 | 
			
		||||
    ServerManager::RunServer(std::move(server_manager));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/kernel/k_event.h"
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
#include "core/hle/service/ipc_helpers.h"
 | 
			
		||||
#include "core/hle/service/kernel_helpers.h"
 | 
			
		||||
#include "core/hle/service/sm/sm.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,6 +123,18 @@ enum class NodeStatus : u8 {
 | 
			
		||||
    Connected,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class WirelessControllerRestriction : u32 {
 | 
			
		||||
    None,
 | 
			
		||||
    Default,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ConnectOption {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(ConnectOption) == 0x4, "ConnectOption is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct NodeLatestUpdate {
 | 
			
		||||
    NodeStateChange state_change;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x7); // Unknown
 | 
			
		||||
@@ -139,9 +151,9 @@ static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct IntentId {
 | 
			
		||||
    u64 local_communication_id;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x2); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
 | 
			
		||||
    u16 scene_id;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x4); // Reserved
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
 | 
			
		||||
 | 
			
		||||
@@ -152,13 +164,14 @@ struct NetworkId {
 | 
			
		||||
static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct Ssid {
 | 
			
		||||
    u8 length{};
 | 
			
		||||
    std::array<char, SsidLengthMax + 1> raw{};
 | 
			
		||||
    u8 length;
 | 
			
		||||
    std::array<char, SsidLengthMax + 1> raw;
 | 
			
		||||
 | 
			
		||||
    Ssid() = default;
 | 
			
		||||
 | 
			
		||||
    constexpr explicit Ssid(std::string_view data) {
 | 
			
		||||
        length = static_cast<u8>(std::min(data.size(), SsidLengthMax));
 | 
			
		||||
        raw = {};
 | 
			
		||||
        data.copy(raw.data(), length);
 | 
			
		||||
        raw[length] = 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -181,7 +194,7 @@ using Ipv4Address = std::array<u8, 4>;
 | 
			
		||||
static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct MacAddress {
 | 
			
		||||
    std::array<u8, 6> raw{};
 | 
			
		||||
    std::array<u8, 6> raw;
 | 
			
		||||
 | 
			
		||||
    friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
 | 
			
		||||
};
 | 
			
		||||
@@ -211,7 +224,7 @@ struct CommonNetworkInfo {
 | 
			
		||||
    WifiChannel channel;
 | 
			
		||||
    LinkLevel link_level;
 | 
			
		||||
    PackedNetworkType network_type;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x4);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
 | 
			
		||||
 | 
			
		||||
@@ -221,9 +234,9 @@ struct NodeInfo {
 | 
			
		||||
    s8 node_id;
 | 
			
		||||
    u8 is_connected;
 | 
			
		||||
    std::array<u8, UserNameBytesMax + 1> user_name;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x1); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x1); // Reserved
 | 
			
		||||
    s16 local_communication_version;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x10); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x10); // Reserved
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
 | 
			
		||||
 | 
			
		||||
@@ -232,14 +245,14 @@ struct LdnNetworkInfo {
 | 
			
		||||
    SecurityMode security_mode;
 | 
			
		||||
    AcceptPolicy station_accept_policy;
 | 
			
		||||
    u8 has_action_frame;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x2); // Padding
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x2); // Padding
 | 
			
		||||
    u8 node_count_max;
 | 
			
		||||
    u8 node_count;
 | 
			
		||||
    std::array<NodeInfo, NodeCountMax> nodes;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x2); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
 | 
			
		||||
    u16 advertise_data_size;
 | 
			
		||||
    std::array<u8, AdvertiseDataSizeMax> advertise_data;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x8C); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES_NOINIT(0x8C); // Reserved
 | 
			
		||||
    u64 random_authentication_id;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
 | 
			
		||||
@@ -250,6 +263,7 @@ struct NetworkInfo {
 | 
			
		||||
    LdnNetworkInfo ldn;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
 | 
			
		||||
static_assert(std::is_trivial_v<NetworkInfo>, "NetworkInfo type must be trivially copyable.");
 | 
			
		||||
 | 
			
		||||
struct SecurityConfig {
 | 
			
		||||
    SecurityMode security_mode;
 | 
			
		||||
@@ -303,4 +317,36 @@ struct AddressList {
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct GroupInfo {
 | 
			
		||||
    std::array<u8, 0x200> info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct CreateNetworkConfig {
 | 
			
		||||
    SecurityConfig security_config;
 | 
			
		||||
    UserConfig user_config;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
    NetworkConfig network_config;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(CreateNetworkConfig) == 0x98, "CreateNetworkConfig is an invalid size");
 | 
			
		||||
 | 
			
		||||
#pragma pack(push, 4)
 | 
			
		||||
struct CreateNetworkConfigPrivate {
 | 
			
		||||
    SecurityConfig security_config;
 | 
			
		||||
    SecurityParameter security_parameter;
 | 
			
		||||
    UserConfig user_config;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
    NetworkConfig network_config;
 | 
			
		||||
};
 | 
			
		||||
#pragma pack(pop)
 | 
			
		||||
static_assert(sizeof(CreateNetworkConfigPrivate) == 0xB8,
 | 
			
		||||
              "CreateNetworkConfigPrivate is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct ConnectNetworkData {
 | 
			
		||||
    SecurityConfig security_config;
 | 
			
		||||
    UserConfig user_config;
 | 
			
		||||
    s32 local_communication_version;
 | 
			
		||||
    ConnectOption option;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(ConnectNetworkData) == 0x7c, "ConnectNetworkData is an invalid size");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								src/core/hle/service/ldn/monitor_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/core/hle/service/ldn/monitor_service.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_serialization.h"
 | 
			
		||||
#include "core/hle/service/ldn/monitor_service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
IMonitorService::IMonitorService(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IMonitorService"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    static const FunctionInfo functions[] = {
 | 
			
		||||
        {0, C<&IMonitorService::GetStateForMonitor>, "GetStateForMonitor"},
 | 
			
		||||
        {1, nullptr, "GetNetworkInfoForMonitor"},
 | 
			
		||||
        {2, nullptr, "GetIpv4AddressForMonitor"},
 | 
			
		||||
        {3, nullptr, "GetDisconnectReasonForMonitor"},
 | 
			
		||||
        {4, nullptr, "GetSecurityParameterForMonitor"},
 | 
			
		||||
        {5, nullptr, "GetNetworkConfigForMonitor"},
 | 
			
		||||
        {100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"},
 | 
			
		||||
        {101, nullptr, "FinalizeMonitor"},
 | 
			
		||||
    };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IMonitorService::~IMonitorService() = default;
 | 
			
		||||
 | 
			
		||||
Result IMonitorService::GetStateForMonitor(Out<State> out_state) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    *out_state = state;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IMonitorService::InitializeMonitor() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    state = State::Initialized;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										28
									
								
								src/core/hle/service/ldn/monitor_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/hle/service/ldn/monitor_service.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
class IMonitorService final : public ServiceFramework<IMonitorService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IMonitorService(Core::System& system_);
 | 
			
		||||
    ~IMonitorService() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result GetStateForMonitor(Out<State> out_state);
 | 
			
		||||
    Result InitializeMonitor();
 | 
			
		||||
 | 
			
		||||
    State state{State::None};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										40
									
								
								src/core/hle/service/ldn/sf_monitor_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/core/hle/service/ldn/sf_monitor_service.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_serialization.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_types.h"
 | 
			
		||||
#include "core/hle/service/ldn/sf_monitor_service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
ISfMonitorService::ISfMonitorService(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "ISfMonitorService"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, C<&ISfMonitorService::Initialize>, "Initialize"},
 | 
			
		||||
            {288, C<&ISfMonitorService::GetGroupInfo>, "GetGroupInfo"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISfMonitorService::~ISfMonitorService() = default;
 | 
			
		||||
 | 
			
		||||
Result ISfMonitorService::Initialize(Out<u32> out_value) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    *out_value = 0;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result ISfMonitorService::GetGroupInfo(
 | 
			
		||||
    OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    *out_group_info = GroupInfo{};
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										26
									
								
								src/core/hle/service/ldn/sf_monitor_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/core/hle/service/ldn/sf_monitor_service.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
struct GroupInfo;
 | 
			
		||||
 | 
			
		||||
class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISfMonitorService(Core::System& system_);
 | 
			
		||||
    ~ISfMonitorService() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result Initialize(Out<u32> out_value);
 | 
			
		||||
    Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										37
									
								
								src/core/hle/service/ldn/sf_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/core/hle/service/ldn/sf_service.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/ldn/sf_service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
ISfService::ISfService(Core::System& system_) : ServiceFramework{system_, "ISfService"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, nullptr, "Initialize"},
 | 
			
		||||
            {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
 | 
			
		||||
            {264, nullptr, "GetNetworkInterfaceLastError"},
 | 
			
		||||
            {272, nullptr, "GetRole"},
 | 
			
		||||
            {280, nullptr, "GetAdvertiseData"},
 | 
			
		||||
            {288, nullptr, "GetGroupInfo"},
 | 
			
		||||
            {296, nullptr, "GetGroupInfo2"},
 | 
			
		||||
            {304, nullptr, "GetGroupOwner"},
 | 
			
		||||
            {312, nullptr, "GetIpConfig"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
            {512, nullptr, "Scan"},
 | 
			
		||||
            {768, nullptr, "CreateGroup"},
 | 
			
		||||
            {776, nullptr, "DestroyGroup"},
 | 
			
		||||
            {784, nullptr, "SetAdvertiseData"},
 | 
			
		||||
            {1536, nullptr, "SendToOtherGroup"},
 | 
			
		||||
            {1544, nullptr, "RecvFromOtherGroup"},
 | 
			
		||||
            {1552, nullptr, "AddAcceptableGroupId"},
 | 
			
		||||
            {1560, nullptr, "ClearAcceptableGroupId"},
 | 
			
		||||
    };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISfService::~ISfService() = default;
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										21
									
								
								src/core/hle/service/ldn/sf_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/core/hle/service/ldn/sf_service.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
class ISfService final : public ServiceFramework<ISfService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISfService(Core::System& system_);
 | 
			
		||||
    ~ISfService() override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										50
									
								
								src/core/hle/service/ldn/sf_service_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/core/hle/service/ldn/sf_service_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_serialization.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_types.h"
 | 
			
		||||
#include "core/hle/service/ldn/sf_service_monitor.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
ISfServiceMonitor::ISfServiceMonitor(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "ISfServiceMonitor"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, C<&ISfServiceMonitor::Initialize>, "Initialize"},
 | 
			
		||||
            {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
 | 
			
		||||
            {264, nullptr, "GetNetworkInterfaceLastError"},
 | 
			
		||||
            {272, nullptr, "GetRole"},
 | 
			
		||||
            {280, nullptr, "GetAdvertiseData"},
 | 
			
		||||
            {281, nullptr, "GetAdvertiseData2"},
 | 
			
		||||
            {288, C<&ISfServiceMonitor::GetGroupInfo>, "GetGroupInfo"},
 | 
			
		||||
            {296, nullptr, "GetGroupInfo2"},
 | 
			
		||||
            {304, nullptr, "GetGroupOwner"},
 | 
			
		||||
            {312, nullptr, "GetIpConfig"},
 | 
			
		||||
            {320, nullptr, "GetLinkLevel"},
 | 
			
		||||
            {328, nullptr, "AttachJoinEvent"},
 | 
			
		||||
            {336, nullptr, "GetMembers"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISfServiceMonitor::~ISfServiceMonitor() = default;
 | 
			
		||||
 | 
			
		||||
Result ISfServiceMonitor::Initialize(Out<u32> out_value) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    *out_value = 0;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result ISfServiceMonitor::GetGroupInfo(
 | 
			
		||||
    OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    *out_group_info = GroupInfo{};
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										26
									
								
								src/core/hle/service/ldn/sf_service_monitor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/core/hle/service/ldn/sf_service_monitor.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
struct GroupInfo;
 | 
			
		||||
 | 
			
		||||
class ISfServiceMonitor final : public ServiceFramework<ISfServiceMonitor> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISfServiceMonitor(Core::System& system_);
 | 
			
		||||
    ~ISfServiceMonitor() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result Initialize(Out<u32> out_value);
 | 
			
		||||
    Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_serialization.h"
 | 
			
		||||
#include "core/hle/service/ldn/system_local_communication_service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, nullptr, "GetState"},
 | 
			
		||||
            {1, nullptr, "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"},
 | 
			
		||||
            {104, nullptr, "SetWirelessControllerRestriction"},
 | 
			
		||||
            {200, nullptr, "OpenAccessPoint"},
 | 
			
		||||
            {201, nullptr, "CloseAccessPoint"},
 | 
			
		||||
            {202, nullptr, "CreateNetwork"},
 | 
			
		||||
            {203, nullptr, "CreateNetworkPrivate"},
 | 
			
		||||
            {204, nullptr, "DestroyNetwork"},
 | 
			
		||||
            {205, nullptr, "Reject"},
 | 
			
		||||
            {206, nullptr, "SetAdvertiseData"},
 | 
			
		||||
            {207, nullptr, "SetStationAcceptPolicy"},
 | 
			
		||||
            {208, nullptr, "AddAcceptFilterEntry"},
 | 
			
		||||
            {209, nullptr, "ClearAcceptFilter"},
 | 
			
		||||
            {300, nullptr, "OpenStation"},
 | 
			
		||||
            {301, nullptr, "CloseStation"},
 | 
			
		||||
            {302, nullptr, "Connect"},
 | 
			
		||||
            {303, nullptr, "ConnectPrivate"},
 | 
			
		||||
            {304, nullptr, "Disconnect"},
 | 
			
		||||
            {400, nullptr, "InitializeSystem"},
 | 
			
		||||
            {401, nullptr, "FinalizeSystem"},
 | 
			
		||||
            {402, nullptr, "SetOperationMode"},
 | 
			
		||||
            {403, C<&ISystemLocalCommunicationService::InitializeSystem2>, "InitializeSystem2"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISystemLocalCommunicationService::~ISystemLocalCommunicationService() = default;
 | 
			
		||||
 | 
			
		||||
Result ISystemLocalCommunicationService::InitializeSystem2() {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
class ISystemLocalCommunicationService final
 | 
			
		||||
    : public ServiceFramework<ISystemLocalCommunicationService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ISystemLocalCommunicationService(Core::System& system_);
 | 
			
		||||
    ~ISystemLocalCommunicationService() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result InitializeSystem2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										320
									
								
								src/core/hle/service/ldn/user_local_communication_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								src/core/hle/service/ldn/user_local_communication_service.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,320 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/hle/kernel/k_event.h"
 | 
			
		||||
#include "core/hle/service/cmif_serialization.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_results.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_types.h"
 | 
			
		||||
#include "core/hle/service/ldn/user_local_communication_service.h"
 | 
			
		||||
#include "core/hle/service/server_manager.h"
 | 
			
		||||
#include "core/internal_network/network.h"
 | 
			
		||||
#include "core/internal_network/network_interface.h"
 | 
			
		||||
#include "network/network.h"
 | 
			
		||||
 | 
			
		||||
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
 | 
			
		||||
#undef CreateEvent
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IUserLocalCommunicationService"},
 | 
			
		||||
      service_context{system, "IUserLocalCommunicationService"},
 | 
			
		||||
      room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, C<&IUserLocalCommunicationService::GetState>, "GetState"},
 | 
			
		||||
            {1, C<&IUserLocalCommunicationService::GetNetworkInfo>, "GetNetworkInfo"},
 | 
			
		||||
            {2, C<&IUserLocalCommunicationService::GetIpv4Address>, "GetIpv4Address"},
 | 
			
		||||
            {3, C<&IUserLocalCommunicationService::GetDisconnectReason>, "GetDisconnectReason"},
 | 
			
		||||
            {4, C<&IUserLocalCommunicationService::GetSecurityParameter>, "GetSecurityParameter"},
 | 
			
		||||
            {5, C<&IUserLocalCommunicationService::GetNetworkConfig>, "GetNetworkConfig"},
 | 
			
		||||
            {100, C<&IUserLocalCommunicationService::AttachStateChangeEvent>, "AttachStateChangeEvent"},
 | 
			
		||||
            {101, C<&IUserLocalCommunicationService::GetNetworkInfoLatestUpdate>, "GetNetworkInfoLatestUpdate"},
 | 
			
		||||
            {102, C<&IUserLocalCommunicationService::Scan>, "Scan"},
 | 
			
		||||
            {103, C<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
 | 
			
		||||
            {104, C<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
 | 
			
		||||
            {200, C<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
 | 
			
		||||
            {201, C<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
 | 
			
		||||
            {202, C<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
 | 
			
		||||
            {203, C<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"},
 | 
			
		||||
            {204, C<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"},
 | 
			
		||||
            {205, nullptr, "Reject"},
 | 
			
		||||
            {206, C<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"},
 | 
			
		||||
            {207, C<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"},
 | 
			
		||||
            {208, C<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"},
 | 
			
		||||
            {209, nullptr, "ClearAcceptFilter"},
 | 
			
		||||
            {300, C<&IUserLocalCommunicationService::OpenStation>, "OpenStation"},
 | 
			
		||||
            {301, C<&IUserLocalCommunicationService::CloseStation>, "CloseStation"},
 | 
			
		||||
            {302, C<&IUserLocalCommunicationService::Connect>, "Connect"},
 | 
			
		||||
            {303, nullptr, "ConnectPrivate"},
 | 
			
		||||
            {304, C<&IUserLocalCommunicationService::Disconnect>, "Disconnect"},
 | 
			
		||||
            {400, C<&IUserLocalCommunicationService::Initialize>, "Initialize"},
 | 
			
		||||
            {401, C<&IUserLocalCommunicationService::Finalize>, "Finalize"},
 | 
			
		||||
            {402, C<&IUserLocalCommunicationService::Initialize2>, "Initialize2"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
    state_change_event =
 | 
			
		||||
        service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IUserLocalCommunicationService::~IUserLocalCommunicationService() {
 | 
			
		||||
    if (is_initialized) {
 | 
			
		||||
        if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
            room_member->Unbind(ldn_packet_received);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    service_context.CloseEvent(state_change_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetState(Out<State> out_state) {
 | 
			
		||||
    *out_state = State::Error;
 | 
			
		||||
 | 
			
		||||
    if (is_initialized) {
 | 
			
		||||
        *out_state = lan_discovery.GetState();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_LDN, "called, state={}", *out_state);
 | 
			
		||||
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetNetworkInfo(
 | 
			
		||||
    OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetIpv4Address(Out<Ipv4Address> out_current_address,
 | 
			
		||||
                                                      Out<Ipv4Address> out_subnet_mask) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
    const auto network_interface = Network::GetSelectedNetworkInterface();
 | 
			
		||||
 | 
			
		||||
    R_UNLESS(network_interface.has_value(), ResultNoIpAddress);
 | 
			
		||||
 | 
			
		||||
    *out_current_address = {Network::TranslateIPv4(network_interface->ip_address)};
 | 
			
		||||
    *out_subnet_mask = {Network::TranslateIPv4(network_interface->subnet_mask)};
 | 
			
		||||
 | 
			
		||||
    // When we're connected to a room, spoof the hosts IP address
 | 
			
		||||
    if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
        if (room_member->IsConnected()) {
 | 
			
		||||
            *out_current_address = room_member->GetFakeIpAddress();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::reverse(std::begin(*out_current_address), std::end(*out_current_address)); // ntohl
 | 
			
		||||
    std::reverse(std::begin(*out_subnet_mask), std::end(*out_subnet_mask));         // ntohl
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetDisconnectReason(
 | 
			
		||||
    Out<DisconnectReason> out_disconnect_reason) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    *out_disconnect_reason = lan_discovery.GetDisconnectReason();
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetSecurityParameter(
 | 
			
		||||
    Out<SecurityParameter> out_security_parameter) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    NetworkInfo info{};
 | 
			
		||||
    R_TRY(lan_discovery.GetNetworkInfo(info));
 | 
			
		||||
 | 
			
		||||
    out_security_parameter->session_id = info.network_id.session_id;
 | 
			
		||||
    std::memcpy(out_security_parameter->data.data(), info.ldn.security_parameter.data(),
 | 
			
		||||
                sizeof(SecurityParameter::data));
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetNetworkConfig(Out<NetworkConfig> out_network_config) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    NetworkInfo info{};
 | 
			
		||||
    R_TRY(lan_discovery.GetNetworkInfo(info));
 | 
			
		||||
 | 
			
		||||
    out_network_config->intent_id = info.network_id.intent_id;
 | 
			
		||||
    out_network_config->channel = info.common.channel;
 | 
			
		||||
    out_network_config->node_count_max = info.ldn.node_count_max;
 | 
			
		||||
    out_network_config->local_communication_version = info.ldn.nodes[0].local_communication_version;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::AttachStateChangeEvent(
 | 
			
		||||
    OutCopyHandle<Kernel::KReadableEvent> out_event) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    *out_event = &state_change_event->GetReadableEvent();
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(
 | 
			
		||||
    OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
 | 
			
		||||
    OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_UNLESS(!out_node_latest_update.empty(), ResultBadInput);
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info, out_node_latest_update));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Scan(
 | 
			
		||||
    Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
 | 
			
		||||
    OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
 | 
			
		||||
             channel, scan_filter.flag, scan_filter.network_type);
 | 
			
		||||
 | 
			
		||||
    R_UNLESS(!out_network_info.empty(), ResultBadInput);
 | 
			
		||||
    R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::ScanPrivate(
 | 
			
		||||
    Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
 | 
			
		||||
    OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
 | 
			
		||||
             channel, scan_filter.flag, scan_filter.network_type);
 | 
			
		||||
 | 
			
		||||
    R_UNLESS(out_network_info.empty(), ResultBadInput);
 | 
			
		||||
    R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::SetWirelessControllerRestriction(
 | 
			
		||||
    WirelessControllerRestriction wireless_restriction) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::OpenAccessPoint() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.OpenAccessPoint());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::CloseAccessPoint() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.CloseAccessPoint());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::CreateNetwork(const CreateNetworkConfig& create_config) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
 | 
			
		||||
                                         create_config.network_config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::CreateNetworkPrivate(
 | 
			
		||||
    const CreateNetworkConfigPrivate& create_config,
 | 
			
		||||
    InArray<AddressEntry, BufferAttr_HipcPointer> address_list) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
 | 
			
		||||
                                         create_config.network_config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::DestroyNetwork() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.DestroyNetwork());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::SetAdvertiseData(
 | 
			
		||||
    InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.SetAdvertiseData(buffer_data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::SetStationAcceptPolicy(AcceptPolicy accept_policy) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_address) {
 | 
			
		||||
    LOG_WARNING(Service_LDN, "(STUBBED) called");
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::OpenStation() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.OpenStation());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::CloseStation() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.CloseStation());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Connect(
 | 
			
		||||
    const ConnectNetworkData& connect_data,
 | 
			
		||||
    InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info) {
 | 
			
		||||
    LOG_INFO(Service_LDN,
 | 
			
		||||
             "called, passphrase_size={}, security_mode={}, "
 | 
			
		||||
             "local_communication_version={}",
 | 
			
		||||
             connect_data.security_config.passphrase_size,
 | 
			
		||||
             connect_data.security_config.security_mode, connect_data.local_communication_version);
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.Connect(*network_info, connect_data.user_config,
 | 
			
		||||
                                   static_cast<u16>(connect_data.local_communication_version)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Disconnect() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.Disconnect());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Initialize(ClientProcessId aruid) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called, process_id={}", aruid.pid);
 | 
			
		||||
 | 
			
		||||
    const auto network_interface = Network::GetSelectedNetworkInterface();
 | 
			
		||||
    R_UNLESS(network_interface, ResultAirplaneModeEnabled);
 | 
			
		||||
 | 
			
		||||
    if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
        ldn_packet_received = room_member->BindOnLdnPacketReceived(
 | 
			
		||||
            [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG_ERROR(Service_LDN, "Couldn't bind callback!");
 | 
			
		||||
        R_RETURN(ResultAirplaneModeEnabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lan_discovery.Initialize([&]() { OnEventFired(); });
 | 
			
		||||
    is_initialized = true;
 | 
			
		||||
    R_SUCCEED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Finalize() {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called");
 | 
			
		||||
    if (auto room_member = room_network.GetRoomMember().lock()) {
 | 
			
		||||
        room_member->Unbind(ldn_packet_received);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    is_initialized = false;
 | 
			
		||||
 | 
			
		||||
    R_RETURN(lan_discovery.Finalize());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result IUserLocalCommunicationService::Initialize2(u32 version, ClientProcessId process_id) {
 | 
			
		||||
    LOG_INFO(Service_LDN, "called, version={}, process_id={}", version, process_id.pid);
 | 
			
		||||
    R_RETURN(Initialize(process_id));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacket& packet) {
 | 
			
		||||
    lan_discovery.ReceivePacket(packet);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IUserLocalCommunicationService::OnEventFired() {
 | 
			
		||||
    state_change_event->Signal();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
							
								
								
									
										103
									
								
								src/core/hle/service/ldn/user_local_communication_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/core/hle/service/ldn/user_local_communication_service.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/cmif_types.h"
 | 
			
		||||
#include "core/hle/service/kernel_helpers.h"
 | 
			
		||||
#include "core/hle/service/ldn/lan_discovery.h"
 | 
			
		||||
#include "core/hle/service/ldn/ldn_types.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Network {
 | 
			
		||||
class RoomNetwork;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::LDN {
 | 
			
		||||
 | 
			
		||||
class IUserLocalCommunicationService final
 | 
			
		||||
    : public ServiceFramework<IUserLocalCommunicationService> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IUserLocalCommunicationService(Core::System& system_);
 | 
			
		||||
    ~IUserLocalCommunicationService() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result GetState(Out<State> out_state);
 | 
			
		||||
 | 
			
		||||
    Result GetNetworkInfo(OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info);
 | 
			
		||||
 | 
			
		||||
    Result GetIpv4Address(Out<Ipv4Address> out_current_address, Out<Ipv4Address> out_subnet_mask);
 | 
			
		||||
 | 
			
		||||
    Result GetDisconnectReason(Out<DisconnectReason> out_disconnect_reason);
 | 
			
		||||
 | 
			
		||||
    Result GetSecurityParameter(Out<SecurityParameter> out_security_parameter);
 | 
			
		||||
 | 
			
		||||
    Result GetNetworkConfig(Out<NetworkConfig> out_network_config);
 | 
			
		||||
 | 
			
		||||
    Result AttachStateChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
 | 
			
		||||
 | 
			
		||||
    Result GetNetworkInfoLatestUpdate(
 | 
			
		||||
        OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
 | 
			
		||||
        OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update);
 | 
			
		||||
 | 
			
		||||
    Result Scan(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
 | 
			
		||||
                OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
 | 
			
		||||
 | 
			
		||||
    Result ScanPrivate(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
 | 
			
		||||
                       OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
 | 
			
		||||
 | 
			
		||||
    Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction);
 | 
			
		||||
 | 
			
		||||
    Result OpenAccessPoint();
 | 
			
		||||
 | 
			
		||||
    Result CloseAccessPoint();
 | 
			
		||||
 | 
			
		||||
    Result CreateNetwork(const CreateNetworkConfig& create_network_Config);
 | 
			
		||||
 | 
			
		||||
    Result CreateNetworkPrivate(const CreateNetworkConfigPrivate& create_network_Config,
 | 
			
		||||
                                InArray<AddressEntry, BufferAttr_HipcPointer> address_list);
 | 
			
		||||
 | 
			
		||||
    Result DestroyNetwork();
 | 
			
		||||
 | 
			
		||||
    Result SetAdvertiseData(InBuffer<BufferAttr_HipcAutoSelect> buffer_data);
 | 
			
		||||
 | 
			
		||||
    Result SetStationAcceptPolicy(AcceptPolicy accept_policy);
 | 
			
		||||
 | 
			
		||||
    Result AddAcceptFilterEntry(MacAddress mac_address);
 | 
			
		||||
 | 
			
		||||
    Result OpenStation();
 | 
			
		||||
 | 
			
		||||
    Result CloseStation();
 | 
			
		||||
 | 
			
		||||
    Result Connect(const ConnectNetworkData& connect_data,
 | 
			
		||||
                   InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info);
 | 
			
		||||
 | 
			
		||||
    Result Disconnect();
 | 
			
		||||
 | 
			
		||||
    Result Initialize(ClientProcessId aruid);
 | 
			
		||||
 | 
			
		||||
    Result Finalize();
 | 
			
		||||
 | 
			
		||||
    Result Initialize2(u32 version, ClientProcessId aruid);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    /// Callback to parse and handle a received LDN packet.
 | 
			
		||||
    void OnLDNPacketReceived(const Network::LDNPacket& packet);
 | 
			
		||||
    void OnEventFired();
 | 
			
		||||
 | 
			
		||||
    KernelHelpers::ServiceContext service_context;
 | 
			
		||||
    Kernel::KEvent* state_change_event;
 | 
			
		||||
    Network::RoomNetwork& room_network;
 | 
			
		||||
    LANDiscovery lan_discovery;
 | 
			
		||||
 | 
			
		||||
    // Callback identifier for the OnLDNPacketReceived event.
 | 
			
		||||
    Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
 | 
			
		||||
 | 
			
		||||
    bool is_initialized{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::LDN
 | 
			
		||||
		Reference in New Issue
	
	Block a user