service/nwm_uds: Add NetworkStatusChangeReason (#5377)

fixes https://github.com/citra-emu/citra/issues/3975
This commit is contained in:
Pengfei Zhu 2022-12-17 23:03:59 +08:00 committed by GitHub
parent 06a9f69d88
commit 9d5ae8e1c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 45 deletions

View file

@ -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);

View file

@ -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];