From 9d5ae8e1c22cbf7d8999b615580dd65eac1f76c1 Mon Sep 17 00:00:00 2001 From: Pengfei Zhu Date: Sat, 17 Dec 2022 23:03:59 +0800 Subject: [PATCH] service/nwm_uds: Add NetworkStatusChangeReason (#5377) fixes https://github.com/citra-emu/citra/issues/3975 --- src/core/hle/service/nwm/nwm_uds.cpp | 76 ++++++++++++++-------------- src/core/hle/service/nwm/nwm_uds.h | 14 ++--- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 579ee159cc..0c6c23e5df 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -124,7 +124,7 @@ void NWM_UDS::BroadcastNodeMap() { void NWM_UDS::HandleNodeMapPacket(const Network::WifiPacket& packet) { std::lock_guard lock(connection_status_mutex); - if (connection_status.status == static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status == NetworkStatus::ConnectedAsHost) { LOG_DEBUG(Service_NWM, "Ignored NodeMapPacket since connection_status is host"); return; } @@ -170,10 +170,10 @@ void NWM_UDS::HandleAssociationResponseFrame(const Network::WifiPacket& packet) "Could not join network"); { std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::Connecting)) { + if (connection_status.status != NetworkStatus::Connecting) { LOG_DEBUG(Service_NWM, "Ignored AssociationResponseFrame because connection status is {}", - connection_status.status); + static_cast(connection_status.status)); return; } } @@ -196,9 +196,9 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { std::lock(hle_lock, lock); if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) { - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is {}", - connection_status.status); + static_cast(connection_status.status)); return; } @@ -255,7 +255,7 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { SendPacket(eapol_logoff); connection_status_event->Signal(); - } else if (connection_status.status == static_cast(NetworkStatus::Connecting)) { + } else if (connection_status.status == NetworkStatus::Connecting) { auto logoff = ParseEAPoLLogoffFrame(packet.data); network_info.host_mac_address = packet.transmitter_address; @@ -282,14 +282,14 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) { } // We're now connected, signal the application - connection_status.status = static_cast(NetworkStatus::ConnectedAsClient); - connection_status.disconnect_reason = static_cast(DisconnectStatus::Connected); + connection_status.status = NetworkStatus::ConnectedAsClient; + connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished; // Some games require ConnectToNetwork to block, for now it doesn't // If blocking is implemented this lock needs to be changed, // otherwise it might cause deadlocks connection_status_event->Signal(); connection_event->Signal(); - } else if (connection_status.status == static_cast(NetworkStatus::ConnectedAsClient)) { + } else if (connection_status.status == NetworkStatus::ConnectedAsClient) { // TODO(B3N30): Remove that section and send/receive a proper connection_status packet // On a 3ds this packet wouldn't be addressed to already connected clients // We use this information because in the current implementation the host @@ -328,11 +328,11 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) { std::unique_lock lock(connection_status_mutex, std::defer_lock); std::lock(hle_lock, lock); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost) && - connection_status.status != static_cast(NetworkStatus::ConnectedAsClient)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost && + connection_status.status != NetworkStatus::ConnectedAsClient) { // TODO(B3N30): Handle spectators LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}", - connection_status.status); + static_cast(connection_status.status)); return; } @@ -347,12 +347,12 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) { // However, we might have received this packet due to a broadcast from the host, in that // case just ignore it. if (packet.destination_address != Network::BroadcastMac && - connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + connection_status.status != 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) && + if (connection_status.status == NetworkStatus::ConnectedAsHost && secure_data.dest_node_id != BroadcastNetworkNodeId) { // Broadcast the packet so the right receiver can get it. // TODO(B3N30): Is there a flag that makes this kind of routing be unicast instead of @@ -390,7 +390,7 @@ void NWM_UDS::StartConnectionSequence(const MacAddress& server) { WifiPacket auth_request; { std::lock_guard lock(connection_status_mutex); - connection_status.status = static_cast(NetworkStatus::Connecting); + connection_status.status = NetworkStatus::Connecting; // TODO(Subv): Handle timeout. @@ -410,9 +410,9 @@ void NWM_UDS::SendAssociationResponseFrame(const MacAddress& address) { { std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}", - connection_status.status); + static_cast(connection_status.status)); return; } @@ -436,10 +436,10 @@ void NWM_UDS::HandleAuthenticationFrame(const Network::WifiPacket& packet) { WifiPacket auth_request; { std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}", - connection_status.status); + static_cast(connection_status.status)); return; } if (node_map.find(packet.transmitter_address) != node_map.end()) { @@ -472,7 +472,7 @@ void NWM_UDS::HandleDeauthenticationFrame(const Network::WifiPacket& packet) { std::unique_lock hle_lock(HLE::g_hle_lock, std::defer_lock); std::unique_lock lock(connection_status_mutex, std::defer_lock); std::lock(hle_lock, lock); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { LOG_ERROR(Service_NWM, "Got deauthentication frame but we are not the host"); return; } @@ -667,8 +667,7 @@ ResultVal> NWM_UDS::Initialize( // Reset the connection status, it contains all zeros after initialization, // except for the actual status value. connection_status = {}; - connection_status.disconnect_reason = static_cast(DisconnectStatus::NotConnected); - connection_status.status = static_cast(NetworkStatus::NotConnected); + connection_status.status = NetworkStatus::NotConnected; node_info.clear(); node_info.push_back(current_node); channel_data.clear(); @@ -856,8 +855,8 @@ ResultCode NWM_UDS::BeginHostingNetwork(const u8* network_info_buffer, // The real UDS module throws a fatal error if this assert fails. ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member."); - connection_status.status = static_cast(NetworkStatus::ConnectedAsHost); - connection_status.disconnect_reason = static_cast(DisconnectStatus::Connected); + connection_status.status = NetworkStatus::ConnectedAsHost; + connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished; // Ensure the application data size is less than the maximum value. ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, @@ -965,7 +964,7 @@ void NWM_UDS::EjectClient(Kernel::HLERequestContext& ctx) { } std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { // Only the host can kick people. rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, ErrorSummary::InvalidState, ErrorLevel::Usage)); @@ -1016,11 +1015,12 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) { // Only a host can destroy std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultCode(ErrCodes::WrongStatus, ErrorModule::UDS, ErrorSummary::InvalidState, ErrorLevel::Status)); - LOG_WARNING(Service_NWM, "called with status {}", connection_status.status); + LOG_WARNING(Service_NWM, "called with status {}", + static_cast(connection_status.status)); return; } @@ -1028,7 +1028,7 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) { u16_le tmp_node_id = connection_status.network_node_id; connection_status = {}; - connection_status.status = static_cast(NetworkStatus::NotConnected); + connection_status.status = NetworkStatus::NotConnected; connection_status.network_node_id = tmp_node_id; node_map.clear(); connection_status_event->Signal(); @@ -1053,11 +1053,11 @@ void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) { WifiPacket deauth; { std::lock_guard lock(connection_status_mutex); - if (connection_status.status == static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status == NetworkStatus::ConnectedAsHost) { // A real 3ds makes strange things here. We do the same u16_le tmp_node_id = connection_status.network_node_id; connection_status = {}; - connection_status.status = static_cast(NetworkStatus::ConnectedAsHost); + connection_status.status = NetworkStatus::ConnectedAsHost; connection_status.network_node_id = tmp_node_id; node_map.clear(); LOG_DEBUG(Service_NWM, "called as a host"); @@ -1067,7 +1067,7 @@ void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) { } u16_le tmp_node_id = connection_status.network_node_id; connection_status = {}; - connection_status.status = static_cast(NetworkStatus::NotConnected); + connection_status.status = NetworkStatus::NotConnected; connection_status.network_node_id = tmp_node_id; node_map.clear(); connection_status_event->Signal(); @@ -1107,8 +1107,8 @@ void NWM_UDS::SendTo(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsClient) && - connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) { + if (connection_status.status != NetworkStatus::ConnectedAsClient && + connection_status.status != NetworkStatus::ConnectedAsHost) { rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, ErrorSummary::InvalidState, ErrorLevel::Status)); return; @@ -1179,9 +1179,9 @@ void NWM_UDS::PullPacket(Kernel::HLERequestContext& ctx) { u32 buff_size = std::min(max_out_buff_size_aligned, 0x172) << 2; std::lock_guard lock(connection_status_mutex); - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost) && - connection_status.status != static_cast(NetworkStatus::ConnectedAsClient) && - connection_status.status != static_cast(NetworkStatus::ConnectedAsSpectator)) { + if (connection_status.status != NetworkStatus::ConnectedAsHost && + connection_status.status != NetworkStatus::ConnectedAsClient && + connection_status.status != NetworkStatus::ConnectedAsSpectator) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, ErrorSummary::InvalidState, ErrorLevel::Status)); @@ -1242,7 +1242,7 @@ void NWM_UDS::GetChannel(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); std::lock_guard lock(connection_status_mutex); - bool is_connected = connection_status.status != static_cast(NetworkStatus::NotConnected); + bool is_connected = connection_status.status != NetworkStatus::NotConnected; u8 channel = is_connected ? network_channel : 0; @@ -1445,7 +1445,7 @@ void NWM_UDS::DecryptBeaconData(Kernel::HLERequestContext& ctx) { // Sends a 802.11 beacon frame with information about the current network. void NWM_UDS::BeaconBroadcastCallback(std::uintptr_t user_data, s64 cycles_late) { // Don't do anything if we're not actually hosting a network - if (connection_status.status != static_cast(NetworkStatus::ConnectedAsHost)) + if (connection_status.status != NetworkStatus::ConnectedAsHost) return; std::vector frame = GenerateBeaconFrame(network_info, node_info); diff --git a/src/core/hle/service/nwm/nwm_uds.h b/src/core/hle/service/nwm/nwm_uds.h index e8eeb360ae..738d42a9b2 100644 --- a/src/core/hle/service/nwm/nwm_uds.h +++ b/src/core/hle/service/nwm/nwm_uds.h @@ -65,7 +65,7 @@ static_assert(sizeof(NodeInfo) == 40, "NodeInfo has incorrect size."); using NodeList = std::vector; -enum class NetworkStatus { +enum class NetworkStatus : u32 { NotConnected = 3, ConnectedAsHost = 6, Connecting = 7, @@ -73,15 +73,15 @@ enum class NetworkStatus { ConnectedAsSpectator = 10, }; -enum class DisconnectStatus { - Connected = 1, - NotConnected = 2, - // TODO(B3N30): Figure out the other values +enum class NetworkStatusChangeReason : u32 { + None = 0, + ConnectionEstablished = 1, + ConnectionLost = 4, }; struct ConnectionStatus { - u32_le status; - u32_le disconnect_reason; + enum_le status; + enum_le status_change_reason; u16_le network_node_id; u16_le changed_nodes; u16_le nodes[UDSMaxNodes];