Skip to content

ams::mitm::ldn::ICommunicationService

LDN Communication Service implementation.

This class implements the IUserLocalCommunicationService interface, handling all LDN operations and forwarding them to our RyuLdn server via the network client.State ManagementThe service maintains an LDN state machine:State changes are notified via the state change event.

Type: LdnStateMachine

Thread-safe state machine.

Type: u64

Error state flag.

Type: u64

Client game process ID.

Type: NetworkInfo

Current network info.

Type: DisconnectReason

Last disconnect reason.

Type: u32

Assigned IPv4 address.

Type: u32

Subnet mask.

Type: ryu_ldn::network::RyuLdnClient

Server communication client.

Type: bool

Server connection status.

Type: LdnNodeMapper

Node ID to IP mapping.

Type: LdnProxyBuffer

Incoming proxy data buffer.

Type: os::Event

Signaled when expected response received.

Type: os::Event

Signaled when scan completes (ScanReplyEnd)

Type: os::Event

Signaled on network error.

Type: os::Event

Signaled when reject reply received.

Type: os::Event

Signaled when RyuLdnClient reaches Ready state.

Type: ryu_ldn::protocol::PacketId

Last received packet ID.

Type: NetworkInfo

Scan results buffer.

Type: size_t

Number of scan results.

Type: uint8_t

Stored advertise data.

Type: size_t

Size of advertise data.

Type: uint8_t

Game version string for CreateAccessPoint.

Type: bool

True when in active network session.

Type: bool

Previous connected state of each node.

Type: ryu_ldn::protocol::NetworkErrorCode

Last error from server.

Type: bool

True if P2P proxy enabled.

Type: ryu_ldn::protocol::ProxyConfig

Current proxy configuration.

Type: ryu_ldn::protocol::ExternalProxyConfig

External proxy config.

Type: *

Connected P2P proxy client (joiner side)

Type: *

Hosted P2P proxy server (host side)

Type: os::ThreadType

Type: std::atomic< bool >

Type: bool

Type: ryu_ldn::protocol::ExternalProxyConfig

Type: NetworkTimeout

Auto-disconnect after idle period.

Type: os::ThreadType

Receive thread (replaces old bg thread)

Type: std::atomic< bool >

Receive thread running flag.

Type: os::SdkMutex

Protects shared state.

Type: ncm::ProgramId

Client program ID (title ID)

Type: u64

LocalCommunicationId from NACP (for LDN filtering)

Type: u16

Expected sceneId from game’s Scan filter (Ryujinx may use 0)

Type: constexpr size_t

Max networks from scan (reduced from 24)

void ICommunicationService(ncm::ProgramId program_id)

Constructor.

program_idProgram ID of the client process (used to replace LocalCommunicationId=-1) @gdb{tag=“LDN:LIFECYCLE”, msg=“Communication service created”}param

Parameters:

  • program_id (ncm::ProgramId)
void ~ICommunicationService()

Destructor.

@gdb{tag=“LDN:LIFECYCLE”, msg=“Communication service destroyed”}

Result GetState(ams::sf::Out< u32 > state)

Get current communication state.

stateOutput state valueparamResult code @gdb{tag=“LDN:OPS”, msg=“GetState”}return

Parameters:

  • state (ams::sf::Out&lt; u32 &gt;)

Returns: Result

Result GetNetworkInfo(ams::sf::Out<> buffer)

Get current network information.

bufferOutput network infoparamResult code @gdb{tag=“LDN:OPS”, msg=“GetNetworkInfo”}return

Parameters:

  • buffer (ams::sf::Out&lt;&gt;)

Returns: Result

Result GetIpv4Address(ams::sf::Out< u32 > address, ams::sf::Out< u32 > mask)

Get assigned IPv4 address.

addressOutput IP address (host byte order)maskOutput subnet mask (host byte order)paramResult code @gdb{tag=“LDN:OPS”, msg=“GetIpv4Address”}return

Parameters:

  • address (ams::sf::Out&lt; u32 &gt;)
  • mask (ams::sf::Out&lt; u32 &gt;)

Returns: Result

Result GetDisconnectReason(ams::sf::Out< u32 > reason)

Get last disconnect reason.

reasonOutput disconnect reasonparamResult code @gdb{tag=“LDN:OPS”, msg=“GetDisconnectReason”}return

Parameters:

  • reason (ams::sf::Out&lt; u32 &gt;)

Returns: Result

Result GetSecurityParameter(ams::sf::Out<> out)

Get security parameters.

outOutput security parameterparamResult code @gdb{tag=“LDN:OPS”, msg=“GetSecurityParameter”}return

Parameters:

  • out (ams::sf::Out&lt;&gt;)

Returns: Result

Result GetNetworkConfig(ams::sf::Out<> out)

Get network configuration.

outOutput network configparamResult code @gdb{tag=“LDN:OPS”, msg=“GetNetworkConfig”}return

Parameters:

  • out (ams::sf::Out&lt;&gt;)

Returns: Result

Result AttachStateChangeEvent(ams::sf::Out< ams::sf::CopyHandle > handle)

Attach to state change event.

handleOutput event handleparamResult code @gdb{tag=“LDN:OPS”, msg=“AttachStateChangeEvent”}return

Parameters:

  • handle (ams::sf::Out&lt; ams::sf::CopyHandle &gt;)

Returns: Result

Result GetNetworkInfoLatestUpdate(ams::sf::Out<> buffer, ams::sf::OutArray<> pUpdates)

Get network info with node updates.

bufferOutput network infopUpdatesOutput node update arrayparamResult code @gdb{tag=“LDN:OPS”, msg=“GetNetworkInfoLatestUpdate”}return

Parameters:

  • buffer (ams::sf::Out&lt;&gt;)
  • pUpdates (ams::sf::OutArray&lt;&gt;)

Returns: Result

Result Scan(ams::sf::Out< u32 > count, ams::sf::OutAutoSelectArray<> buffer, u16 channel, const ScanFilter & filter)

Scan for available networks.

countOutput number of networks foundbufferOutput network info arraychannelChannel to scan (0 for all)filterScan filterparamResult code @gdb{tag=“LDN:OPS”, msg=“Scan”}return

Parameters:

  • count (ams::sf::Out&lt; u32 &gt;)
  • buffer (ams::sf::OutAutoSelectArray&lt;&gt;)
  • channel (u16)
  • filter (const ScanFilter &)

Returns: Result

Result OpenAccessPoint()

Open as access point (host mode)

Result code @gdb{tag=“LDN:OPS”, msg=“OpenAccessPoint”}return

Returns: Result

Result CloseAccessPoint()

Close access point.

Result code @gdb{tag=“LDN:OPS”, msg=“CloseAccessPoint”}return

Returns: Result

Result CreateNetwork(const& data)

Create a network.

dataNetwork creation configurationparamResult code @gdb{tag=“LDN:OPS”, msg=“CreateNetwork”}return

Parameters:

  • data (const&)

Returns: Result

Result DestroyNetwork()

Destroy the network.

Result code @gdb{tag=“LDN:OPS”, msg=“DestroyNetwork”}return

Returns: Result

Result SetAdvertiseData(ams::sf::InAutoSelectBuffer data)

Set advertise data.

dataAdvertise data bufferparamResult code @gdb{tag=“LDN:OPS”, msg=“SetAdvertiseData”}return

Parameters:

  • data (ams::sf::InAutoSelectBuffer)

Returns: Result

Result SetStationAcceptPolicy(u8 policy)

Set station accept policy.

policyAccept policyparamResult code @gdb{tag=“LDN:OPS”, msg=“SetStationAcceptPolicy”}return

Parameters:

  • policy (u8)

Returns: Result

Result OpenStation()

Open as station (client mode)

Result code @gdb{tag=“LDN:OPS”, msg=“OpenStation”}return

Returns: Result

Result CloseStation()

Close station.

Result code @gdb{tag=“LDN:OPS”, msg=“CloseStation”}return

Returns: Result

Result Connect(const& dat, const& data)

Connect to a network.

datConnection parameters (security config, user config, version, option)dataNetwork to connect toparamResult code @gdb{tag=“LDN:OPS”, msg=“Connect”}return

Parameters:

  • dat (const&)
  • data (const&)

Returns: Result

Result Disconnect()

Disconnect from network.

Result code @gdb{tag=“LDN:OPS”, msg=“Disconnect”}return

Returns: Result

Result Initialize(const ams::sf::ClientProcessId & client_process_id)

Initialize the service.

client_process_idClient process IDparamResult code @gdb{tag=“LDN:OPS”, msg=“Initialize”}return

Parameters:

  • client_process_id (const ams::sf::ClientProcessId &)

Returns: Result

Result Finalize()

Finalize the service.

Result code @gdb{tag=“LDN:OPS”, msg=“Finalize”}return

Returns: Result

Result InitializeSystem2(u64 unk, const ams::sf::ClientProcessId & client_process_id)

Initialize with system flags.

unkUnknown parameterclient_process_idClient process IDparamResult code @gdb{tag=“LDN:OPS”, msg=“InitializeSystem2”}return

Parameters:

  • unk (u64)
  • client_process_id (const ams::sf::ClientProcessId &)

Returns: Result

Result ScanPrivate(ams::sf::Out< u32 > count, ams::sf::OutAutoSelectArray<> buffer, u16 channel, const ScanFilter & filter)

Scan for private networks.

Same asbut includes private networks in results.countOutput number of networks foundbufferOutput network info arraychannelChannel to scan (0 for all)filterScan filterparamResult code @gdb{tag=“LDN:OPS”, msg=“ScanPrivate”}return

Parameters:

  • count (ams::sf::Out&lt; u32 &gt;)
  • buffer (ams::sf::OutAutoSelectArray&lt;&gt;)
  • channel (u16)
  • filter (const ScanFilter &)

Returns: Result

Result CreateNetworkPrivate(const CreateNetworkPrivateConfig & data, ams::sf::InPointerBuffer addressList)

Create a private (password-protected) network.

dataNetwork configuration including security parameteraddressListAddress list bufferparamResult code @gdb{tag=“LDN:OPS”, msg=“CreateNetworkPrivate”}return

Parameters:

  • data (const CreateNetworkPrivateConfig &)
  • addressList (ams::sf::InPointerBuffer)

Returns: Result

Result ConnectPrivate(const ConnectPrivateData & data)

Connect to a private network.

dataConnection data including security parameterparamResult code @gdb{tag=“LDN:OPS”, msg=“ConnectPrivate”}return

Parameters:

  • data (const ConnectPrivateData &)

Returns: Result

Result SetWirelessControllerRestriction()

Set wireless controller restriction.

Result code (stub) @gdb{tag=“LDN:OPS”, msg=“SetWirelessControllerRestriction”}return

Returns: Result

Result Reject(u32 nodeId)

Reject a node from the network.

nodeIdNode ID to rejectparamResult code @gdb{tag=“LDN:OPS”, msg=“Reject: nodeId=%u”, args=“$x1”}return

Parameters:

  • nodeId (u32)

Returns: Result

Result AddAcceptFilterEntry()

Add entry to accept filter.

Result code (stub) @gdb{tag=“LDN:OPS”, msg=“AddAcceptFilterEntry”}return

Returns: Result

Result ClearAcceptFilter()

Clear accept filter.

Result code (stub) @gdb{tag=“LDN:OPS”, msg=“ClearAcceptFilter”}return

Returns: Result

ryu_ldn::network::ClientOpResult SendProxyDataToServer(const ryu_ldn::protocol::ProxyDataHeader & header, const void * data, size_t data_len)

Send ProxyData to server (for BSD MITM callback)

This method is called by the BSD MITM layer to send game socket data through the LDN server connection.headerProxyData header with addressing infodataPacket payloaddata_lenPayload lengthparamClientOpResult indicating success or failure @gdb{tag=“LDN:OPS”, msg=“SendProxyDataToServer”}return

Parameters:

  • header (const ryu_ldn::protocol::ProxyDataHeader &)
  • data (const void *)
  • data_len (size_t)

Returns: ryu_ldn::network::ClientOpResult

Result ConnectToServer()

Connect to RyuLdn server.

Result code @gdb{tag=“LDN:ASYNC”, msg=“ConnectToServer: entering”}return

Returns: Result

void DisconnectFromServer()

Disconnect from RyuLdn server.

@gdb{tag=“LDN:ASYNC”, msg=“DisconnectFromServer: entering”}

bool IsServerConnected()

Check if connected to server.

true if connected and ready @gdb{tag=“LDN:ASYNC”, msg=“IsServerConnected: queried”}return

Returns: bool

void HandleServerPacket(ryu_ldn::protocol::PacketId id, const uint8_t * data, size_t size)

Handle packet received from server.

idPacket typedataPacket payloadsizePayload size @gdb{tag=“LDN:ASYNC”, msg=“HandleServerPacket: id=%u size=%zu”, args=“$x2, $x3”}param

Parameters:

  • id (ryu_ldn::protocol::PacketId)
  • data (const uint8_t *)
  • size (size_t)
void HandleConnectedPacket(const uint8_t * data, size_t size)

Handle Connected packet from server.

Server confirms we joined/created a network. Containswith node data, which we fix up (sceneId, localCommId, channel) and then signal state change.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
void HandleSyncNetworkPacket(const uint8_t * data, size_t size)

Handle SyncNetwork packet from server.

Server sends updated network state. We update, fix sceneId/localCommId, and signal state change.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
void HandleExternalProxyPacket(const uint8_t * data, size_t size)

Handle ExternalProxy packet from server.

Server sends P2P proxy info. We skip self-loopback, ignore if P2P disabled, or spawn a connect thread for remote peers.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
void HandleProxyDataPacket(const uint8_t * data, size_t size)

Handle ProxyData packet from server.

Server relays game data from other players. Routes to BSD MITM proxy sockets or falls back to legacy buffer.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
void HandleNetworkErrorPacket(const uint8_t * data, size_t size)

Handle NetworkError packet from server.

Server reports a network error. Disables P2P on PortUnreachable and signals the error event.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
void HandleScanReplyPacket(const uint8_t * data, size_t size)

Handle ScanReply packet from server.

Server sends one network info for each discovered network. Results are stored in the scan buffer and sceneId/localCommId are fixed for Ryujinx compatibility.dataPacket payloadsizePayload sizeparam

Parameters:

  • data (const uint8_t *)
  • size (size_t)
bool WaitForResponse(ryu_ldn::protocol::PacketId expected_id, uint64_t timeout_ms)

Wait for a specific packet response from server.

expected_idExpected packet typetimeout_msTimeout in millisecondsparamtrue if packet received, false on timeout @gdb{tag=“LDN:ASYNC”, msg=“WaitForResponse: expected_id=%u timeout_ms=%lu”, args=“$x1, $x2”}return

Parameters:

  • expected_id (ryu_ldn::protocol::PacketId)
  • timeout_ms (uint64_t)

Returns: bool

void ReceiveThreadFunc()

Receive thread main loop — reads packets, dispatches immediately.

@gdb{tag=“LDN:ASYNC”, msg=“ReceiveThreadFunc: loop iteration”}

u8 FindLocalNodeId()

Find our local node ID in the network info.

Searches through the nodes array to find the node matching our m_ipv4_address. Returns 0xFF if not found.Node ID (0-7) or 0xFF if not foundreturn

Returns: u8

void SetGameVersion(const uint8_t * version)

Set game version from local_communication_version.

Converts version number to string format for RyuNetworkConfig.versionVersion buffer (16 bytes)param

Parameters:

  • version (const uint8_t *)
ryu_ldn::protocol::NetworkErrorCode ConsumeNetworkError()

Consume last network error (like Ryujinx ConsumeNetworkError)

Returns the last error and resets it to None.Last network error codereturn

Returns: ryu_ldn::protocol::NetworkErrorCode

void HandleExternalProxyConnect(const ryu_ldn::protocol::ExternalProxyConfig & config)

Handle ExternalProxy packet - connect to P2P host.

Called when server sends ExternalProxyConfig indicating a P2P host is available. Creates P2pProxyClient and establishes direct connection.configExternalProxyConfig from master serverparam

Parameters:

  • config (const ryu_ldn::protocol::ExternalProxyConfig &)
void DisconnectP2pProxy()

Disconnect from P2P proxy if connected.

bool StartP2pProxyServer()

Start P2P proxy server for hosting.

Called when creating a network. Starts P2pProxyServer and attempts UPnP NAT punch to allow direct P2P connections.true if server started (UPnP may or may not succeed)return

Returns: bool

void StopP2pProxyServer()

Stop P2P proxy server if running.

void HandleExternalProxyToken(const& token)

Handle ExternalProxyToken from master server.

Called when master server notifies us a joiner is about to connect. Adds token to waiting list for authentication.tokenToken for the expected joinerparam

Parameters:

  • token (const&)
void ReceiveThreadEntry(void * arg)

Receive thread entry point.

argPointer toinstance @gdb{tag=“LDN:ASYNC”, msg=“ReceiveThreadEntry: thread started arg=%p”, args=“$x0”}param

Parameters:

  • arg (void *)
void P2pConnectThreadEntry(void * arg)

Async P2P connect thread entry — see m_p2p_connect_thread.

argPointer toinstance @gdb{tag=“LDN:ASYNC”, msg=“P2pConnectThreadEntry: thread started arg=%p”, args=“$x0”}param

Parameters:

  • arg (void *)
void OnInactivityTimeout()

Static callback for inactivity timeout.

Called when the timeout expires. Disconnects from server.Called when theexpires (no network activity for 6 seconds). Disconnects from the server to save resources. Like Ryujinx _timeout callback that calls DisconnectInternal().