service/nwm_uds: Add NetworkStatusChangeReason (#5377)
fixes https://github.com/citra-emu/citra/issues/3975
This commit is contained in:
		| @@ -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<u32>(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<u32>(NetworkStatus::Connecting)) { | ||||
|         if (connection_status.status != NetworkStatus::Connecting) { | ||||
|             LOG_DEBUG(Service_NWM, | ||||
|                       "Ignored AssociationResponseFrame because connection status is {}", | ||||
|                       connection_status.status); | ||||
|                       static_cast<u32>(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<u32>(NetworkStatus::ConnectedAsHost)) { | ||||
|         if (connection_status.status != NetworkStatus::ConnectedAsHost) { | ||||
|             LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is {}", | ||||
|                       connection_status.status); | ||||
|                       static_cast<u32>(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<u32>(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<u32>(NetworkStatus::ConnectedAsClient); | ||||
|         connection_status.disconnect_reason = static_cast<u32>(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<u32>(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<u32>(NetworkStatus::ConnectedAsHost) && | ||||
|         connection_status.status != static_cast<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(NetworkStatus::ConnectedAsHost)) { | ||||
|         if (connection_status.status != NetworkStatus::ConnectedAsHost) { | ||||
|             LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}", | ||||
|                       connection_status.status); | ||||
|                       static_cast<u32>(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<u32>(NetworkStatus::ConnectedAsHost)) { | ||||
|             if (connection_status.status != NetworkStatus::ConnectedAsHost) { | ||||
|                 LOG_ERROR(Service_NWM, | ||||
|                           "Connection sequence aborted, because connection status is {}", | ||||
|                           connection_status.status); | ||||
|                           static_cast<u32>(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<u32>(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<std::shared_ptr<Kernel::Event>> 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<u32>(DisconnectStatus::NotConnected); | ||||
|         connection_status.status = static_cast<u32>(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<u32>(NetworkStatus::ConnectedAsHost); | ||||
|         connection_status.disconnect_reason = static_cast<u32>(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<u8>(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<u8>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(NetworkStatus::ConnectedAsClient) && | ||||
|         connection_status.status != static_cast<u32>(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<u32>(max_out_buff_size_aligned, 0x172) << 2; | ||||
|  | ||||
|     std::lock_guard lock(connection_status_mutex); | ||||
|     if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost) && | ||||
|         connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) && | ||||
|         connection_status.status != static_cast<u32>(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<u32>(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<u32>(NetworkStatus::ConnectedAsHost)) | ||||
|     if (connection_status.status != NetworkStatus::ConnectedAsHost) | ||||
|         return; | ||||
|  | ||||
|     std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info); | ||||
|   | ||||
| @@ -65,7 +65,7 @@ static_assert(sizeof(NodeInfo) == 40, "NodeInfo has incorrect size."); | ||||
|  | ||||
| using NodeList = std::vector<NodeInfo>; | ||||
|  | ||||
| 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<NetworkStatus> status; | ||||
|     enum_le<NetworkStatusChangeReason> status_change_reason; | ||||
|     u16_le network_node_id; | ||||
|     u16_le changed_nodes; | ||||
|     u16_le nodes[UDSMaxNodes]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Pengfei Zhu
					Pengfei Zhu