aboutsummaryrefslogtreecommitdiff
path: root/src/core/internal_network
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/internal_network')
-rw-r--r--src/core/internal_network/network.cpp11
-rw-r--r--src/core/internal_network/network.h4
-rw-r--r--src/core/internal_network/socket_proxy.cpp29
-rw-r--r--src/core/internal_network/socket_proxy.h3
4 files changed, 39 insertions, 8 deletions
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp
index 01d37fb35b..d1c436aa08 100644
--- a/src/core/internal_network/network.cpp
+++ b/src/core/internal_network/network.cpp
@@ -722,6 +722,17 @@ std::optional<IPv4Address> GetHostIPv4Address() {
return TranslateIPv4(network_interface->ip_address);
}
+std::optional<IPv4Address> GetRoomIPv4Address() {
+ if (const auto room_member = GetRoomMember().lock()) {
+ // The room host and moderators are in the Moderator state instead of Joined
+ const auto state = room_member->GetState();
+ if (state == RoomMember::State::Joined || state == RoomMember::State::Moderator) {
+ return room_member->GetFakeIpAddress();
+ }
+ }
+ return std::nullopt;
+}
+
std::string IPv4AddressToString(IPv4Address ip_addr) {
std::array<char, INET_ADDRSTRLEN> buf = {};
ASSERT(inet_ntop(AF_INET, &ip_addr, buf.data(), sizeof(buf)) == buf.data());
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h
index 2c9ae523c5..a598f75348 100644
--- a/src/core/internal_network/network.h
+++ b/src/core/internal_network/network.h
@@ -121,6 +121,10 @@ constexpr IPv4Address TranslateIPv4(in_addr addr) {
/// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array
std::optional<IPv4Address> GetHostIPv4Address();
+/// @brief Returns the fake IPv4 address of the joined room, the emulated network while in a room
+/// @return nullopt outside a room and while still joining it
+std::optional<IPv4Address> GetRoomIPv4Address();
+
std::string IPv4AddressToString(IPv4Address ip_addr);
u32 IPv4AddressToInteger(IPv4Address ip_addr);
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp
index 83eb2ce9d0..6c2f79da6e 100644
--- a/src/core/internal_network/socket_proxy.cpp
+++ b/src/core/internal_network/socket_proxy.cpp
@@ -43,9 +43,21 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) {
LOG_INFO(Network, "Received broadcast packet, but not configured for broadcast mode");
return;
}
+ }
- auto decompressed = packet;
- decompressed.data = Common::Compression::DecompressDataZSTD(packet.data);
+ // Decompress without the lock, so the game thread does not wait for it
+ ProxyPacket decompressed{
+ .local_endpoint = packet.local_endpoint,
+ .remote_endpoint = packet.remote_endpoint,
+ .protocol = packet.protocol,
+ .broadcast = packet.broadcast,
+ .data = Common::Compression::DecompressDataZSTD(packet.data),
+ };
+ {
+ std::lock_guard guard(packets_mutex);
+ if (closed) {
+ return;
+ }
received_packets.push(std::move(decompressed));
}
packets_cv.notify_one();
@@ -152,26 +164,28 @@ std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, So
std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> message, SockAddrIn* addr,
std::size_t max_length) {
- ProxyPacket& packet = received_packets.front();
+ const ProxyPacket& packet = received_packets.front();
if (addr) {
addr->family = Domain::INET;
addr->ip = packet.local_endpoint.ip; // The senders ip address
addr->portno = packet.local_endpoint.portno; // The senders port number
}
- const std::size_t read_bytes = (std::min)(packet.data.size(), max_length);
- std::memcpy(message.data(), packet.data.data(), read_bytes);
+ const std::span<const u8> unread = std::span{packet.data}.subspan(front_read_offset);
+ const std::size_t read_bytes = (std::min)(unread.size(), max_length);
+ std::memcpy(message.data(), unread.data(), read_bytes);
if ((flags & FLAG_MSG_PEEK) != 0) {
return {static_cast<s32>(read_bytes), Errno::SUCCESS};
}
- if (protocol == Protocol::TCP && read_bytes < packet.data.size()) {
+ if (protocol == Protocol::TCP && read_bytes < unread.size()) {
// Keep the unread part of the stream for the next call
- packet.data.erase(packet.data.begin(), packet.data.begin() + read_bytes);
+ front_read_offset += read_bytes;
} else {
// Like BSD recv(), the rest of a datagram that does not fit is discarded
received_packets.pop();
+ front_read_offset = 0;
}
return {static_cast<s32>(read_bytes), Errno::SUCCESS};
@@ -240,6 +254,7 @@ Errno ProxySocket::Close() {
fd = INVALID_SOCKET;
closed = true;
received_packets = {};
+ front_read_offset = 0;
}
packets_cv.notify_all();
diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h
index 8343fcbae1..d2bd7aae77 100644
--- a/src/core/internal_network/socket_proxy.h
+++ b/src/core/internal_network/socket_proxy.h
@@ -90,7 +90,8 @@ private:
SockAddrIn local_endpoint{};
bool blocking = true;
std::queue<ProxyPacket> received_packets;
- Protocol protocol;
+ std::size_t front_read_offset = 0; ///< Bytes of the front TCP packet that were already read
+ Protocol protocol{};
std::mutex packets_mutex;
std::condition_variable packets_cv;