From 4918f86622afb4eba6af3c6093f00b39ab0fc6d7 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sun, 31 May 2020 10:46:04 +0800 Subject: [PATCH 1/3] service/nwm_uds: Ensure consistency regarding node IDs Previously, when connecting, the host was using the incorrect node_id to update `node_info`. This is an attempt to fix tywald's problem with MH, reported on Discord a while ago. I'm not sure if this would actually fix that though. --- src/core/hle/service/nwm/nwm_uds.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 831f6c87ed..5e11d63048 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -226,9 +226,7 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { connection_status.nodes[node_id - 1] = node.network_node_id; connection_status.total_nodes++; - u8 current_nodes = network_info.total_nodes; - node_info[current_nodes] = node; - + node_info[node_id - 1] = node; network_info.total_nodes++; node_map[packet.transmitter_address].node_id = node.network_node_id; From 9965ce693805877da562756ec3177cc14a86badd Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Tue, 2 Jun 2020 22:42:45 +0800 Subject: [PATCH 2/3] nwm_uds: Make sure client node information match host's This change is not HW tested as I do not have 3 3DSes, but this should make sure that all the members of the network hold the same `node_info`, `nodes` and the bitmasks, etc. --- src/core/hle/service/nwm/nwm_uds.cpp | 40 ++++++++++++++++++--------- src/core/hle/service/nwm/uds_data.cpp | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 5e11d63048..0198b60752 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -266,13 +266,18 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { connection_status.max_nodes = logoff.max_nodes; node_info.clear(); - node_info.reserve(network_info.max_nodes); - for (std::size_t index = 0; index < logoff.connected_nodes; ++index) { - connection_status.node_bitmask |= 1 << index; - connection_status.changed_nodes |= 1 << index; - connection_status.nodes[index] = logoff.nodes[index].network_node_id; + node_info.resize(network_info.max_nodes); + for (const auto& node : logoff.nodes) { + const u16 index = node.network_node_id; + if (!index) { + continue; + } - node_info.emplace_back(DeserializeNodeInfo(logoff.nodes[index])); + connection_status.node_bitmask |= 1 << (index - 1); + connection_status.changed_nodes |= 1 << (index - 1); + connection_status.nodes[index - 1] = index; + + node_info[index - 1] = DeserializeNodeInfo(node); } // We're now connected, signal the application @@ -291,17 +296,26 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { network_info.total_nodes = logoff.connected_nodes; connection_status.total_nodes = logoff.connected_nodes; + std::memset(connection_status.nodes, 0, sizeof(connection_status.nodes)); + + const auto old_bitmask = connection_status.node_bitmask; + connection_status.node_bitmask = 0; node_info.clear(); - node_info.reserve(network_info.max_nodes); - for (std::size_t index = 0; index < logoff.connected_nodes; ++index) { - if ((connection_status.node_bitmask & (1 << index)) == 0) { - connection_status.changed_nodes |= 1 << index; + node_info.resize(network_info.max_nodes); + for (const auto& node : logoff.nodes) { + const u16 index = node.network_node_id; + if (!index) { + continue; } - connection_status.nodes[index] = logoff.nodes[index].network_node_id; - connection_status.node_bitmask |= 1 << index; - node_info.emplace_back(DeserializeNodeInfo(logoff.nodes[index])); + + connection_status.node_bitmask |= 1 << (index - 1); + connection_status.nodes[index - 1] = index; + + node_info[index - 1] = DeserializeNodeInfo(node); } + connection_status.changed_nodes = old_bitmask ^ connection_status.node_bitmask; + connection_status_event->Signal(); } } diff --git a/src/core/hle/service/nwm/uds_data.cpp b/src/core/hle/service/nwm/uds_data.cpp index cda37b2dc1..7952e329b7 100644 --- a/src/core/hle/service/nwm/uds_data.cpp +++ b/src/core/hle/service/nwm/uds_data.cpp @@ -354,7 +354,7 @@ std::vector GenerateEAPoLLogoffFrame(const MacAddress& mac_address, u16 netw eapol_logoff.connected_nodes = total_nodes; eapol_logoff.max_nodes = max_nodes; - for (std::size_t index = 0; index < total_nodes; ++index) { + for (std::size_t index = 0; index < max_nodes; ++index) { const auto& node_info = nodes[index]; auto& node = eapol_logoff.nodes[index]; From b34ceb89c59e826bd1039a1fb6b5fc29af7341e9 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 4 Jun 2020 23:06:10 +0800 Subject: [PATCH 3/3] nwm_uds: Change ASSERT to LOG_ERROR This might be caused by some packet/status delay within the enet protocol, or may be caused by our not properly handling disconnection. Anyway, this situation *can* happen, and we should not crash Citra for a non-critical error. --- src/core/hle/service/nwm/nwm_uds.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 0198b60752..ff6b9b1975 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -344,9 +344,11 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) { // The packet wasn't addressed to us, we can only act as a router if we're the host. // However, we might have received this packet due to a broadcast from the host, in that // case just ignore it. - ASSERT_MSG(packet.destination_address == Network::BroadcastMac || - connection_status.status == static_cast(NetworkStatus::ConnectedAsHost), - "Can't be a router if we're not a host"); + if (packet.destination_address != Network::BroadcastMac && + connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + LOG_ERROR(Service_NWM, "Received packet addressed to others but we're not a host"); + return; + } if (connection_status.status == static_cast(NetworkStatus::ConnectedAsHost) && secure_data.dest_node_id != BroadcastNetworkNodeId) {