aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-11-02 23:40:30 +0100
committercirakg <cirakg@cirakg.xyz>2026-11-02 23:42:50 +0100
commit3e10d48548a285172ea7cb1f94c58783e1d97754 (patch)
tree203de9fd00993656728c37b3e148eac66f954065 /src/core/hle
parent693529b27ec898b867ad5806a0174f69597decc9 (diff)
network: fix room host LAN Play and room socket review issues
The room host and room moderators are in the Moderator state, not Joined, so the airplane mode override for joined rooms did not apply to them and LAN Play still returned them to the menu. Accept both states. Share the room address override between the NIFM profile and IP config calls so they cannot drift apart. recv() on a room TCP socket now waited for the receive timeout, because Recv goes through RecvFrom. Room TCP sockets have no peer, so keep the previous immediate end-of-stream result when nothing is queued. Close() now drops queued packets and wakes a blocked recv, which then fails with EBADF. The socket state that the room thread reads when it queues a packet is now guarded by the packet mutex. Assisted-by: Claude Opus 5.5 (investigation and implementation)
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/nifm/nifm.cpp41
1 files changed, 21 insertions, 20 deletions
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 153b0f2193..e0a23f7a63 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -73,17 +73,17 @@ static u128 MakeUuidFromName(std::string_view name) {
// A joined room is the emulated network, even in airplane mode. Its sockets only reach room
// members, and LAN games (e.g. Mario Kart World LAN Play) need their connection request accepted.
static bool IsNetworkAvailable() {
- if (const auto room_member = Network::GetRoomMember().lock();
- room_member && room_member->GetState() == Network::RoomMember::State::Joined) {
- return true;
+ if (const auto room_member = Network::GetRoomMember().lock()) {
+ // The room host and moderators are in the Moderator state instead of Joined
+ const auto state = room_member->GetState();
+ if (state == Network::RoomMember::State::Joined ||
+ state == Network::RoomMember::State::Moderator) {
+ return true;
+ }
}
return Network::GetHostIPv4Address().has_value() && !Settings::values.airplane_mode.GetValue();
}
-// Room fake IPs are spread over 192.168.0.0/16, and some room servers give members different /24s.
-// A host /24 mask would then put room members on different subnets, so LAN games ignore each other.
-constexpr Network::IPv4Address RoomSubnetMask{255, 255, 0, 0};
-
// This is nn::nifm::RequestState
enum class RequestState : u32 {
NotSubmitted = 1,
@@ -124,6 +124,17 @@ struct IpAddressSetting {
};
static_assert(sizeof(IpAddressSetting) == 0xD, "IpAddressSetting has incorrect size.");
+// Room fake IPs are spread over 192.168.0.0/16, and some room servers give members different /24s.
+// A host /24 mask would then put room members on different subnets, so LAN games ignore each other.
+constexpr Network::IPv4Address RoomSubnetMask{255, 255, 0, 0};
+
+static void ApplyRoomAddress(const Network::RoomMember& room_member, IpAddressSetting& setting) {
+ if (room_member.IsConnected()) {
+ setting.ip_address = room_member.GetFakeIpAddress();
+ setting.subnet_mask = RoomSubnetMask;
+ }
+}
+
// This is nn::nifm::DnsSetting
struct DnsSetting {
bool is_automatic{};
@@ -585,11 +596,7 @@ void IGeneralService::GetCurrentNetworkProfile(HLERequestContext& ctx) {
std::strncpy(profile.network_name.data(), st.ssid, sizeof(profile.network_name) - 1);
if (auto room_member = Network::GetRoomMember().lock()) {
- if (room_member->IsConnected()) {
- profile.ip_setting_data.ip_address_setting.ip_address =
- room_member->GetFakeIpAddress();
- profile.ip_setting_data.ip_address_setting.subnet_mask = RoomSubnetMask;
- }
+ ApplyRoomAddress(*room_member, profile.ip_setting_data.ip_address_setting);
profile.ip_setting_data.dns_setting.secondary_dns = {8, 8, 8, 8};
}
@@ -726,10 +733,7 @@ void IGeneralService::GetNetworkProfile(HLERequestContext& ctx) {
}();
if (auto room_member = Network::GetRoomMember().lock()) {
- if (room_member->IsConnected()) {
- profile.ip_setting_data.ip_address_setting.ip_address = room_member->GetFakeIpAddress();
- profile.ip_setting_data.ip_address_setting.subnet_mask = RoomSubnetMask;
- }
+ ApplyRoomAddress(*room_member, profile.ip_setting_data.ip_address_setting);
}
ctx.WriteBuffer(profile);
@@ -917,10 +921,7 @@ void IGeneralService::GetCurrentIpConfigInfo(HLERequestContext& ctx) {
}
if (auto room_member = Network::GetRoomMember().lock()) {
- if (room_member->IsConnected()) {
- info.ip.ip_address = room_member->GetFakeIpAddress();
- info.ip.subnet_mask = RoomSubnetMask;
- }
+ ApplyRoomAddress(*room_member, info.ip);
info.dns.is_automatic = true;
info.dns.primary_dns = {1, 1, 1, 1};
info.dns.secondary_dns = {8, 8, 8, 8};