citra-emu
/
citra-canary
Archived
1
0
Fork 0

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) { void NWM_UDS::HandleNodeMapPacket(const Network::WifiPacket& packet) {
std::lock_guard lock(connection_status_mutex); 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"); LOG_DEBUG(Service_NWM, "Ignored NodeMapPacket since connection_status is host");
return; return;
} }
@ -170,10 +170,10 @@ void NWM_UDS::HandleAssociationResponseFrame(const Network::WifiPacket& packet)
"Could not join network"); "Could not join network");
{ {
std::lock_guard lock(connection_status_mutex); 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, LOG_DEBUG(Service_NWM,
"Ignored AssociationResponseFrame because connection status is {}", "Ignored AssociationResponseFrame because connection status is {}",
connection_status.status); static_cast<u32>(connection_status.status));
return; return;
} }
} }
@ -196,9 +196,9 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
std::lock(hle_lock, lock); std::lock(hle_lock, lock);
if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) { 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 {}", LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is {}",
connection_status.status); static_cast<u32>(connection_status.status));
return; return;
} }
@ -255,7 +255,7 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
SendPacket(eapol_logoff); SendPacket(eapol_logoff);
connection_status_event->Signal(); 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); auto logoff = ParseEAPoLLogoffFrame(packet.data);
network_info.host_mac_address = packet.transmitter_address; 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 // We're now connected, signal the application
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient); connection_status.status = NetworkStatus::ConnectedAsClient;
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected); connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
// Some games require ConnectToNetwork to block, for now it doesn't // Some games require ConnectToNetwork to block, for now it doesn't
// If blocking is implemented this lock needs to be changed, // If blocking is implemented this lock needs to be changed,
// otherwise it might cause deadlocks // otherwise it might cause deadlocks
connection_status_event->Signal(); connection_status_event->Signal();
connection_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 // 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 // On a 3ds this packet wouldn't be addressed to already connected clients
// We use this information because in the current implementation the host // 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::unique_lock lock(connection_status_mutex, std::defer_lock);
std::lock(hle_lock, lock); std::lock(hle_lock, lock);
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost) && if (connection_status.status != NetworkStatus::ConnectedAsHost &&
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient)) { connection_status.status != NetworkStatus::ConnectedAsClient) {
// TODO(B3N30): Handle spectators // TODO(B3N30): Handle spectators
LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}", LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}",
connection_status.status); static_cast<u32>(connection_status.status));
return; 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 // However, we might have received this packet due to a broadcast from the host, in that
// case just ignore it. // case just ignore it.
if (packet.destination_address != Network::BroadcastMac && 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"); LOG_ERROR(Service_NWM, "Received packet addressed to others but we're not a host");
return; return;
} }
if (connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost) && if (connection_status.status == NetworkStatus::ConnectedAsHost &&
secure_data.dest_node_id != BroadcastNetworkNodeId) { secure_data.dest_node_id != BroadcastNetworkNodeId) {
// Broadcast the packet so the right receiver can get it. // 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 // 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; WifiPacket auth_request;
{ {
std::lock_guard lock(connection_status_mutex); std::lock_guard lock(connection_status_mutex);
connection_status.status = static_cast<u32>(NetworkStatus::Connecting); connection_status.status = NetworkStatus::Connecting;
// TODO(Subv): Handle timeout. // TODO(Subv): Handle timeout.
@ -410,9 +410,9 @@ void NWM_UDS::SendAssociationResponseFrame(const MacAddress& address) {
{ {
std::lock_guard lock(connection_status_mutex); 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 {}", LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}",
connection_status.status); static_cast<u32>(connection_status.status));
return; return;
} }
@ -436,10 +436,10 @@ void NWM_UDS::HandleAuthenticationFrame(const Network::WifiPacket& packet) {
WifiPacket auth_request; WifiPacket auth_request;
{ {
std::lock_guard lock(connection_status_mutex); 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, LOG_ERROR(Service_NWM,
"Connection sequence aborted, because connection status is {}", "Connection sequence aborted, because connection status is {}",
connection_status.status); static_cast<u32>(connection_status.status));
return; return;
} }
if (node_map.find(packet.transmitter_address) != node_map.end()) { 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 hle_lock(HLE::g_hle_lock, std::defer_lock);
std::unique_lock lock(connection_status_mutex, std::defer_lock); std::unique_lock lock(connection_status_mutex, std::defer_lock);
std::lock(hle_lock, 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"); LOG_ERROR(Service_NWM, "Got deauthentication frame but we are not the host");
return; return;
} }
@ -667,8 +667,7 @@ ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
// Reset the connection status, it contains all zeros after initialization, // Reset the connection status, it contains all zeros after initialization,
// except for the actual status value. // except for the actual status value.
connection_status = {}; connection_status = {};
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::NotConnected); connection_status.status = NetworkStatus::NotConnected;
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
node_info.clear(); node_info.clear();
node_info.push_back(current_node); node_info.push_back(current_node);
channel_data.clear(); 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. // 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."); 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.status = NetworkStatus::ConnectedAsHost;
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected); connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
// Ensure the application data size is less than the maximum value. // Ensure the application data size is less than the maximum value.
ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, 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); 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. // Only the host can kick people.
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
ErrorSummary::InvalidState, ErrorLevel::Usage)); ErrorSummary::InvalidState, ErrorLevel::Usage));
@ -1016,11 +1015,12 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) {
// Only a host can destroy // Only a host can destroy
std::lock_guard lock(connection_status_mutex); 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); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultCode(ErrCodes::WrongStatus, ErrorModule::UDS, ErrorSummary::InvalidState, rb.Push(ResultCode(ErrCodes::WrongStatus, ErrorModule::UDS, ErrorSummary::InvalidState,
ErrorLevel::Status)); 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; return;
} }
@ -1028,7 +1028,7 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) {
u16_le tmp_node_id = connection_status.network_node_id; u16_le tmp_node_id = connection_status.network_node_id;
connection_status = {}; connection_status = {};
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected); connection_status.status = NetworkStatus::NotConnected;
connection_status.network_node_id = tmp_node_id; connection_status.network_node_id = tmp_node_id;
node_map.clear(); node_map.clear();
connection_status_event->Signal(); connection_status_event->Signal();
@ -1053,11 +1053,11 @@ void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) {
WifiPacket deauth; WifiPacket deauth;
{ {
std::lock_guard lock(connection_status_mutex); 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 // A real 3ds makes strange things here. We do the same
u16_le tmp_node_id = connection_status.network_node_id; u16_le tmp_node_id = connection_status.network_node_id;
connection_status = {}; connection_status = {};
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost); connection_status.status = NetworkStatus::ConnectedAsHost;
connection_status.network_node_id = tmp_node_id; connection_status.network_node_id = tmp_node_id;
node_map.clear(); node_map.clear();
LOG_DEBUG(Service_NWM, "called as a host"); 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; u16_le tmp_node_id = connection_status.network_node_id;
connection_status = {}; connection_status = {};
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected); connection_status.status = NetworkStatus::NotConnected;
connection_status.network_node_id = tmp_node_id; connection_status.network_node_id = tmp_node_id;
node_map.clear(); node_map.clear();
connection_status_event->Signal(); connection_status_event->Signal();
@ -1107,8 +1107,8 @@ void NWM_UDS::SendTo(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
std::lock_guard lock(connection_status_mutex); std::lock_guard lock(connection_status_mutex);
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) && if (connection_status.status != NetworkStatus::ConnectedAsClient &&
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) { connection_status.status != NetworkStatus::ConnectedAsHost) {
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
ErrorSummary::InvalidState, ErrorLevel::Status)); ErrorSummary::InvalidState, ErrorLevel::Status));
return; 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; u32 buff_size = std::min<u32>(max_out_buff_size_aligned, 0x172) << 2;
std::lock_guard lock(connection_status_mutex); std::lock_guard lock(connection_status_mutex);
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost) && if (connection_status.status != NetworkStatus::ConnectedAsHost &&
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) && connection_status.status != NetworkStatus::ConnectedAsClient &&
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsSpectator)) { connection_status.status != NetworkStatus::ConnectedAsSpectator) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
ErrorSummary::InvalidState, ErrorLevel::Status)); ErrorSummary::InvalidState, ErrorLevel::Status));
@ -1242,7 +1242,7 @@ void NWM_UDS::GetChannel(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
std::lock_guard lock(connection_status_mutex); 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; 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. // Sends a 802.11 beacon frame with information about the current network.
void NWM_UDS::BeaconBroadcastCallback(std::uintptr_t user_data, s64 cycles_late) { void NWM_UDS::BeaconBroadcastCallback(std::uintptr_t user_data, s64 cycles_late) {
// Don't do anything if we're not actually hosting a network // 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; return;
std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info); 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>; using NodeList = std::vector<NodeInfo>;
enum class NetworkStatus { enum class NetworkStatus : u32 {
NotConnected = 3, NotConnected = 3,
ConnectedAsHost = 6, ConnectedAsHost = 6,
Connecting = 7, Connecting = 7,
@ -73,15 +73,15 @@ enum class NetworkStatus {
ConnectedAsSpectator = 10, ConnectedAsSpectator = 10,
}; };
enum class DisconnectStatus { enum class NetworkStatusChangeReason : u32 {
Connected = 1, None = 0,
NotConnected = 2, ConnectionEstablished = 1,
// TODO(B3N30): Figure out the other values ConnectionLost = 4,
}; };
struct ConnectionStatus { struct ConnectionStatus {
u32_le status; enum_le<NetworkStatus> status;
u32_le disconnect_reason; enum_le<NetworkStatusChangeReason> status_change_reason;
u16_le network_node_id; u16_le network_node_id;
u16_le changed_nodes; u16_le changed_nodes;
u16_le nodes[UDSMaxNodes]; u16_le nodes[UDSMaxNodes];