diff options
Diffstat (limited to 'src/core/internal_network')
| -rw-r--r-- | src/core/internal_network/network.cpp | 61 | ||||
| -rw-r--r-- | src/core/internal_network/network.h | 43 | ||||
| -rw-r--r-- | src/core/internal_network/socket_proxy.cpp | 282 | ||||
| -rw-r--r-- | src/core/internal_network/socket_proxy.h | 102 | ||||
| -rw-r--r-- | src/core/internal_network/sockets.h | 136 |
5 files changed, 524 insertions, 100 deletions
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 36c43cc8f..160cc83e4 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "core/internal_network/network.h" | 32 | #include "core/internal_network/network.h" |
| 33 | #include "core/internal_network/network_interface.h" | 33 | #include "core/internal_network/network_interface.h" |
| 34 | #include "core/internal_network/sockets.h" | 34 | #include "core/internal_network/sockets.h" |
| 35 | #include "network/network.h" | ||
| 35 | 36 | ||
| 36 | namespace Network { | 37 | namespace Network { |
| 37 | 38 | ||
| @@ -114,7 +115,10 @@ Errno TranslateNativeError(int e) { | |||
| 114 | return Errno::NETDOWN; | 115 | return Errno::NETDOWN; |
| 115 | case WSAENETUNREACH: | 116 | case WSAENETUNREACH: |
| 116 | return Errno::NETUNREACH; | 117 | return Errno::NETUNREACH; |
| 118 | case WSAEMSGSIZE: | ||
| 119 | return Errno::MSGSIZE; | ||
| 117 | default: | 120 | default: |
| 121 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | ||
| 118 | return Errno::OTHER; | 122 | return Errno::OTHER; |
| 119 | } | 123 | } |
| 120 | } | 124 | } |
| @@ -125,7 +129,6 @@ using SOCKET = int; | |||
| 125 | using WSAPOLLFD = pollfd; | 129 | using WSAPOLLFD = pollfd; |
| 126 | using ULONG = u64; | 130 | using ULONG = u64; |
| 127 | 131 | ||
| 128 | constexpr SOCKET INVALID_SOCKET = -1; | ||
| 129 | constexpr SOCKET SOCKET_ERROR = -1; | 132 | constexpr SOCKET SOCKET_ERROR = -1; |
| 130 | 133 | ||
| 131 | constexpr int SD_RECEIVE = SHUT_RD; | 134 | constexpr int SD_RECEIVE = SHUT_RD; |
| @@ -206,7 +209,10 @@ Errno TranslateNativeError(int e) { | |||
| 206 | return Errno::NETDOWN; | 209 | return Errno::NETDOWN; |
| 207 | case ENETUNREACH: | 210 | case ENETUNREACH: |
| 208 | return Errno::NETUNREACH; | 211 | return Errno::NETUNREACH; |
| 212 | case EMSGSIZE: | ||
| 213 | return Errno::MSGSIZE; | ||
| 209 | default: | 214 | default: |
| 215 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | ||
| 210 | return Errno::OTHER; | 216 | return Errno::OTHER; |
| 211 | } | 217 | } |
| 212 | } | 218 | } |
| @@ -329,16 +335,6 @@ PollEvents TranslatePollRevents(short revents) { | |||
| 329 | return result; | 335 | return result; |
| 330 | } | 336 | } |
| 331 | 337 | ||
| 332 | template <typename T> | ||
| 333 | Errno SetSockOpt(SOCKET fd, int option, T value) { | ||
| 334 | const int result = | ||
| 335 | setsockopt(fd, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); | ||
| 336 | if (result != SOCKET_ERROR) { | ||
| 337 | return Errno::SUCCESS; | ||
| 338 | } | ||
| 339 | return GetAndLogLastError(); | ||
| 340 | } | ||
| 341 | |||
| 342 | } // Anonymous namespace | 338 | } // Anonymous namespace |
| 343 | 339 | ||
| 344 | NetworkInstance::NetworkInstance() { | 340 | NetworkInstance::NetworkInstance() { |
| @@ -350,26 +346,15 @@ NetworkInstance::~NetworkInstance() { | |||
| 350 | } | 346 | } |
| 351 | 347 | ||
| 352 | std::optional<IPv4Address> GetHostIPv4Address() { | 348 | std::optional<IPv4Address> GetHostIPv4Address() { |
| 353 | const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); | 349 | const auto interface = Network::GetSelectedNetworkInterface(); |
| 354 | const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); | 350 | if (!interface.has_value()) { |
| 355 | if (network_interfaces.size() == 0) { | 351 | LOG_ERROR(Network, "GetSelectedNetworkInterface returned no interface"); |
| 356 | LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); | ||
| 357 | return {}; | 352 | return {}; |
| 358 | } | 353 | } |
| 359 | 354 | ||
| 360 | const auto res = | 355 | char ip_addr[16] = {}; |
| 361 | std::ranges::find_if(network_interfaces, [&selected_network_interface](const auto& iface) { | 356 | ASSERT(inet_ntop(AF_INET, &interface->ip_address, ip_addr, sizeof(ip_addr)) != nullptr); |
| 362 | return iface.name == selected_network_interface; | 357 | return TranslateIPv4(interface->ip_address); |
| 363 | }); | ||
| 364 | |||
| 365 | if (res != network_interfaces.end()) { | ||
| 366 | char ip_addr[16] = {}; | ||
| 367 | ASSERT(inet_ntop(AF_INET, &res->ip_address, ip_addr, sizeof(ip_addr)) != nullptr); | ||
| 368 | return TranslateIPv4(res->ip_address); | ||
| 369 | } else { | ||
| 370 | LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); | ||
| 371 | return {}; | ||
| 372 | } | ||
| 373 | } | 358 | } |
| 374 | 359 | ||
| 375 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { | 360 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { |
| @@ -412,7 +397,19 @@ Socket::~Socket() { | |||
| 412 | fd = INVALID_SOCKET; | 397 | fd = INVALID_SOCKET; |
| 413 | } | 398 | } |
| 414 | 399 | ||
| 415 | Socket::Socket(Socket&& rhs) noexcept : fd{std::exchange(rhs.fd, INVALID_SOCKET)} {} | 400 | Socket::Socket(Socket&& rhs) noexcept { |
| 401 | fd = std::exchange(rhs.fd, INVALID_SOCKET); | ||
| 402 | } | ||
| 403 | |||
| 404 | template <typename T> | ||
| 405 | Errno Socket::SetSockOpt(SOCKET _fd, int option, T value) { | ||
| 406 | const int result = | ||
| 407 | setsockopt(_fd, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); | ||
| 408 | if (result != SOCKET_ERROR) { | ||
| 409 | return Errno::SUCCESS; | ||
| 410 | } | ||
| 411 | return GetAndLogLastError(); | ||
| 412 | } | ||
| 416 | 413 | ||
| 417 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | 414 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { |
| 418 | fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol)); | 415 | fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol)); |
| @@ -423,7 +420,7 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | |||
| 423 | return GetAndLogLastError(); | 420 | return GetAndLogLastError(); |
| 424 | } | 421 | } |
| 425 | 422 | ||
| 426 | std::pair<Socket::AcceptResult, Errno> Socket::Accept() { | 423 | std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { |
| 427 | sockaddr addr; | 424 | sockaddr addr; |
| 428 | socklen_t addrlen = sizeof(addr); | 425 | socklen_t addrlen = sizeof(addr); |
| 429 | const SOCKET new_socket = accept(fd, &addr, &addrlen); | 426 | const SOCKET new_socket = accept(fd, &addr, &addrlen); |
| @@ -634,4 +631,8 @@ bool Socket::IsOpened() const { | |||
| 634 | return fd != INVALID_SOCKET; | 631 | return fd != INVALID_SOCKET; |
| 635 | } | 632 | } |
| 636 | 633 | ||
| 634 | void Socket::HandleProxyPacket(const ProxyPacket& packet) { | ||
| 635 | LOG_WARNING(Network, "ProxyPacket received, but not in Proxy mode!"); | ||
| 636 | } | ||
| 637 | |||
| 637 | } // namespace Network | 638 | } // namespace Network |
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h index 10e5ef10d..36994c22e 100644 --- a/src/core/internal_network/network.h +++ b/src/core/internal_network/network.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/socket_types.h" | ||
| 11 | 12 | ||
| 12 | #ifdef _WIN32 | 13 | #ifdef _WIN32 |
| 13 | #include <winsock2.h> | 14 | #include <winsock2.h> |
| @@ -17,6 +18,7 @@ | |||
| 17 | 18 | ||
| 18 | namespace Network { | 19 | namespace Network { |
| 19 | 20 | ||
| 21 | class SocketBase; | ||
| 20 | class Socket; | 22 | class Socket; |
| 21 | 23 | ||
| 22 | /// Error code for network functions | 24 | /// Error code for network functions |
| @@ -31,46 +33,11 @@ enum class Errno { | |||
| 31 | HOSTUNREACH, | 33 | HOSTUNREACH, |
| 32 | NETDOWN, | 34 | NETDOWN, |
| 33 | NETUNREACH, | 35 | NETUNREACH, |
| 36 | TIMEDOUT, | ||
| 37 | MSGSIZE, | ||
| 34 | OTHER, | 38 | OTHER, |
| 35 | }; | 39 | }; |
| 36 | 40 | ||
| 37 | /// Address families | ||
| 38 | enum class Domain { | ||
| 39 | INET, ///< Address family for IPv4 | ||
| 40 | }; | ||
| 41 | |||
| 42 | /// Socket types | ||
| 43 | enum class Type { | ||
| 44 | STREAM, | ||
| 45 | DGRAM, | ||
| 46 | RAW, | ||
| 47 | SEQPACKET, | ||
| 48 | }; | ||
| 49 | |||
| 50 | /// Protocol values for sockets | ||
| 51 | enum class Protocol { | ||
| 52 | ICMP, | ||
| 53 | TCP, | ||
| 54 | UDP, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /// Shutdown mode | ||
| 58 | enum class ShutdownHow { | ||
| 59 | RD, | ||
| 60 | WR, | ||
| 61 | RDWR, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /// Array of IPv4 address | ||
| 65 | using IPv4Address = std::array<u8, 4>; | ||
| 66 | |||
| 67 | /// Cross-platform sockaddr structure | ||
| 68 | struct SockAddrIn { | ||
| 69 | Domain family; | ||
| 70 | IPv4Address ip; | ||
| 71 | u16 portno; | ||
| 72 | }; | ||
| 73 | |||
| 74 | /// Cross-platform poll fd structure | 41 | /// Cross-platform poll fd structure |
| 75 | 42 | ||
| 76 | enum class PollEvents : u16 { | 43 | enum class PollEvents : u16 { |
| @@ -86,7 +53,7 @@ enum class PollEvents : u16 { | |||
| 86 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); | 53 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); |
| 87 | 54 | ||
| 88 | struct PollFD { | 55 | struct PollFD { |
| 89 | Socket* socket; | 56 | SocketBase* socket; |
| 90 | PollEvents events; | 57 | PollEvents events; |
| 91 | PollEvents revents; | 58 | PollEvents revents; |
| 92 | }; | 59 | }; |
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp new file mode 100644 index 000000000..6e8924822 --- /dev/null +++ b/src/core/internal_network/socket_proxy.cpp | |||
| @@ -0,0 +1,282 @@ | |||
| 1 | // Copyright 2022 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <chrono> | ||
| 6 | #include <thread> | ||
| 7 | |||
| 8 | #include "common/assert.h" | ||
| 9 | #include "common/logging/log.h" | ||
| 10 | #include "core/internal_network/network.h" | ||
| 11 | #include "core/internal_network/network_interface.h" | ||
| 12 | #include "core/internal_network/socket_proxy.h" | ||
| 13 | |||
| 14 | namespace Network { | ||
| 15 | |||
| 16 | ProxySocket::ProxySocket(RoomNetwork& room_network_) noexcept : room_network{room_network_} {} | ||
| 17 | |||
| 18 | ProxySocket::ProxySocket(ProxySocket&& rhs) noexcept : room_network{rhs.room_network} { | ||
| 19 | fd = std::exchange(rhs.fd, INVALID_SOCKET); | ||
| 20 | } | ||
| 21 | |||
| 22 | ProxySocket::~ProxySocket() { | ||
| 23 | if (fd == INVALID_SOCKET) { | ||
| 24 | return; | ||
| 25 | } | ||
| 26 | fd = INVALID_SOCKET; | ||
| 27 | } | ||
| 28 | |||
| 29 | void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) { | ||
| 30 | if (protocol != packet.protocol || local_endpoint.portno != packet.remote_endpoint.portno || | ||
| 31 | closed) { | ||
| 32 | return; | ||
| 33 | } | ||
| 34 | std::lock_guard<std::mutex> guard(packets_mutex); | ||
| 35 | received_packets.push(packet); | ||
| 36 | } | ||
| 37 | |||
| 38 | template <typename T> | ||
| 39 | Errno ProxySocket::SetSockOpt(SOCKET _fd, int option, T value) { | ||
| 40 | socket_options[option] = reinterpret_cast<const char*>(&value); | ||
| 41 | return Errno::SUCCESS; | ||
| 42 | } | ||
| 43 | |||
| 44 | Errno ProxySocket::Initialize(Domain domain, Type type, Protocol socket_protocol) { | ||
| 45 | protocol = socket_protocol; | ||
| 46 | socket_options[0x1008] = reinterpret_cast<const char*>(&type); | ||
| 47 | |||
| 48 | return Errno::SUCCESS; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::pair<ProxySocket::AcceptResult, Errno> ProxySocket::Accept() { | ||
| 52 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 53 | return {AcceptResult{}, Errno::SUCCESS}; | ||
| 54 | } | ||
| 55 | |||
| 56 | Errno ProxySocket::Connect(SockAddrIn addr_in) { | ||
| 57 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 58 | return Errno::SUCCESS; | ||
| 59 | } | ||
| 60 | |||
| 61 | std::pair<SockAddrIn, Errno> ProxySocket::GetPeerName() { | ||
| 62 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 63 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 64 | } | ||
| 65 | |||
| 66 | std::pair<SockAddrIn, Errno> ProxySocket::GetSockName() { | ||
| 67 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 68 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 69 | } | ||
| 70 | |||
| 71 | Errno ProxySocket::Bind(SockAddrIn addr) { | ||
| 72 | if (is_bound) { | ||
| 73 | LOG_WARNING(Network, "Rebinding Socket is unimplemented!"); | ||
| 74 | return Errno::SUCCESS; | ||
| 75 | } | ||
| 76 | local_endpoint = addr; | ||
| 77 | is_bound = true; | ||
| 78 | |||
| 79 | return Errno::SUCCESS; | ||
| 80 | } | ||
| 81 | |||
| 82 | Errno ProxySocket::Listen(s32 backlog) { | ||
| 83 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 84 | return Errno::SUCCESS; | ||
| 85 | } | ||
| 86 | |||
| 87 | Errno ProxySocket::Shutdown(ShutdownHow how) { | ||
| 88 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 89 | return Errno::SUCCESS; | ||
| 90 | } | ||
| 91 | |||
| 92 | std::pair<s32, Errno> ProxySocket::Recv(int flags, std::vector<u8>& message) { | ||
| 93 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 94 | ASSERT(flags == 0); | ||
| 95 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 96 | |||
| 97 | return {static_cast<s32>(0), Errno::SUCCESS}; | ||
| 98 | } | ||
| 99 | |||
| 100 | std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { | ||
| 101 | ASSERT(flags == 0); | ||
| 102 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 103 | |||
| 104 | { | ||
| 105 | std::lock_guard<std::mutex> guard(packets_mutex); | ||
| 106 | if (received_packets.size() > 0) { | ||
| 107 | return ReceivePacket(flags, message, addr, message.size()); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | if (blocking) { | ||
| 112 | if (receive_timeout > 0) { | ||
| 113 | std::this_thread::sleep_for(std::chrono::milliseconds(receive_timeout)); | ||
| 114 | } | ||
| 115 | } else { | ||
| 116 | return {-1, Errno::AGAIN}; | ||
| 117 | } | ||
| 118 | |||
| 119 | std::lock_guard<std::mutex> guard(packets_mutex); | ||
| 120 | if (received_packets.size() > 0) { | ||
| 121 | return ReceivePacket(flags, message, addr, message.size()); | ||
| 122 | } | ||
| 123 | |||
| 124 | return {-1, Errno::TIMEDOUT}; | ||
| 125 | } | ||
| 126 | |||
| 127 | std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& message, | ||
| 128 | SockAddrIn* addr, std::size_t max_length) { | ||
| 129 | ProxyPacket& packet = received_packets.front(); | ||
| 130 | if (addr) { | ||
| 131 | addr->family = Domain::INET; | ||
| 132 | addr->ip = packet.local_endpoint.ip; // The senders ip address | ||
| 133 | addr->portno = packet.local_endpoint.portno; // The senders port number | ||
| 134 | } | ||
| 135 | |||
| 136 | bool peek = (flags & FLAG_MSG_PEEK) != 0; | ||
| 137 | std::size_t read_bytes; | ||
| 138 | if (packet.data.size() > max_length) { | ||
| 139 | read_bytes = max_length; | ||
| 140 | message.clear(); | ||
| 141 | std::copy(packet.data.begin(), packet.data.begin() + read_bytes, | ||
| 142 | std::back_inserter(message)); | ||
| 143 | message.resize(max_length); | ||
| 144 | |||
| 145 | if (protocol == Protocol::UDP) { | ||
| 146 | if (!peek) { | ||
| 147 | received_packets.pop(); | ||
| 148 | } | ||
| 149 | return {-1, Errno::MSGSIZE}; | ||
| 150 | } else if (protocol == Protocol::TCP) { | ||
| 151 | std::vector<u8> numArray(packet.data.size() - max_length); | ||
| 152 | std::copy(packet.data.begin() + max_length, packet.data.end(), | ||
| 153 | std::back_inserter(numArray)); | ||
| 154 | packet.data = numArray; | ||
| 155 | } | ||
| 156 | } else { | ||
| 157 | read_bytes = packet.data.size(); | ||
| 158 | message.clear(); | ||
| 159 | std::copy(packet.data.begin(), packet.data.end(), std::back_inserter(message)); | ||
| 160 | message.resize(max_length); | ||
| 161 | if (!peek) { | ||
| 162 | received_packets.pop(); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | return {static_cast<u32>(read_bytes), Errno::SUCCESS}; | ||
| 167 | } | ||
| 168 | |||
| 169 | std::pair<s32, Errno> ProxySocket::Send(const std::vector<u8>& message, int flags) { | ||
| 170 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 171 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 172 | ASSERT(flags == 0); | ||
| 173 | |||
| 174 | return {static_cast<s32>(0), Errno::SUCCESS}; | ||
| 175 | } | ||
| 176 | |||
| 177 | void ProxySocket::SendPacket(ProxyPacket& packet) { | ||
| 178 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 179 | if (room_member->IsConnected()) { | ||
| 180 | room_member->SendProxyPacket(packet); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& message, | ||
| 186 | const SockAddrIn* addr) { | ||
| 187 | ASSERT(flags == 0); | ||
| 188 | |||
| 189 | if (!is_bound) { | ||
| 190 | LOG_ERROR(Network, "ProxySocket is not bound!"); | ||
| 191 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 195 | if (!room_member->IsConnected()) { | ||
| 196 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | ProxyPacket packet; | ||
| 201 | packet.local_endpoint = local_endpoint; | ||
| 202 | packet.remote_endpoint = *addr; | ||
| 203 | packet.protocol = protocol; | ||
| 204 | packet.broadcast = broadcast; | ||
| 205 | |||
| 206 | auto& ip = local_endpoint.ip; | ||
| 207 | auto ipv4 = Network::GetHostIPv4Address(); | ||
| 208 | // If the ip is all zeroes (INADDR_ANY) or if it matches the hosts ip address, | ||
| 209 | // replace it with a "fake" routing address | ||
| 210 | if (std::all_of(ip.begin(), ip.end(), [](u8 i) { return i == 0; }) || (ipv4 && ipv4 == ip)) { | ||
| 211 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 212 | packet.local_endpoint.ip = room_member->GetFakeIpAddress(); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | packet.data.clear(); | ||
| 217 | std::copy(message.begin(), message.end(), std::back_inserter(packet.data)); | ||
| 218 | |||
| 219 | SendPacket(packet); | ||
| 220 | |||
| 221 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 222 | } | ||
| 223 | |||
| 224 | Errno ProxySocket::Close() { | ||
| 225 | fd = INVALID_SOCKET; | ||
| 226 | closed = true; | ||
| 227 | |||
| 228 | return Errno::SUCCESS; | ||
| 229 | } | ||
| 230 | |||
| 231 | Errno ProxySocket::SetLinger(bool enable, u32 linger) { | ||
| 232 | struct Linger { | ||
| 233 | u16 linger_enable; | ||
| 234 | u16 linger_time; | ||
| 235 | } values; | ||
| 236 | values.linger_enable = enable ? 1 : 0; | ||
| 237 | values.linger_time = static_cast<u16>(linger); | ||
| 238 | |||
| 239 | return SetSockOpt(fd, SO_LINGER, values); | ||
| 240 | } | ||
| 241 | |||
| 242 | Errno ProxySocket::SetReuseAddr(bool enable) { | ||
| 243 | return SetSockOpt<u32>(fd, SO_REUSEADDR, enable ? 1 : 0); | ||
| 244 | } | ||
| 245 | |||
| 246 | Errno ProxySocket::SetBroadcast(bool enable) { | ||
| 247 | broadcast = enable; | ||
| 248 | return SetSockOpt<u32>(fd, SO_BROADCAST, enable ? 1 : 0); | ||
| 249 | } | ||
| 250 | |||
| 251 | Errno ProxySocket::SetSndBuf(u32 value) { | ||
| 252 | return SetSockOpt(fd, SO_SNDBUF, value); | ||
| 253 | } | ||
| 254 | |||
| 255 | Errno ProxySocket::SetKeepAlive(bool enable) { | ||
| 256 | return Errno::SUCCESS; | ||
| 257 | } | ||
| 258 | |||
| 259 | Errno ProxySocket::SetRcvBuf(u32 value) { | ||
| 260 | return SetSockOpt(fd, SO_RCVBUF, value); | ||
| 261 | } | ||
| 262 | |||
| 263 | Errno ProxySocket::SetSndTimeo(u32 value) { | ||
| 264 | send_timeout = value; | ||
| 265 | return SetSockOpt(fd, SO_SNDTIMEO, static_cast<int>(value)); | ||
| 266 | } | ||
| 267 | |||
| 268 | Errno ProxySocket::SetRcvTimeo(u32 value) { | ||
| 269 | receive_timeout = value; | ||
| 270 | return SetSockOpt(fd, SO_RCVTIMEO, static_cast<int>(value)); | ||
| 271 | } | ||
| 272 | |||
| 273 | Errno ProxySocket::SetNonBlock(bool enable) { | ||
| 274 | blocking = !enable; | ||
| 275 | return Errno::SUCCESS; | ||
| 276 | } | ||
| 277 | |||
| 278 | bool ProxySocket::IsOpened() const { | ||
| 279 | return fd != INVALID_SOCKET; | ||
| 280 | } | ||
| 281 | |||
| 282 | } // namespace Network | ||
diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h new file mode 100644 index 000000000..ef7d5b554 --- /dev/null +++ b/src/core/internal_network/socket_proxy.h | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | // Copyright 2022 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <mutex> | ||
| 8 | #include <vector> | ||
| 9 | #include <queue> | ||
| 10 | |||
| 11 | #include "core/internal_network/sockets.h" | ||
| 12 | #include "network/network.h" | ||
| 13 | |||
| 14 | namespace Network { | ||
| 15 | |||
| 16 | class ProxySocket : public SocketBase { | ||
| 17 | public: | ||
| 18 | ProxySocket(RoomNetwork& room_network_) noexcept; | ||
| 19 | ~ProxySocket() override; | ||
| 20 | |||
| 21 | ProxySocket(const ProxySocket&) = delete; | ||
| 22 | ProxySocket& operator=(const ProxySocket&) = delete; | ||
| 23 | |||
| 24 | ProxySocket(ProxySocket&& rhs) noexcept; | ||
| 25 | |||
| 26 | // Avoid closing sockets implicitly | ||
| 27 | ProxySocket& operator=(ProxySocket&&) noexcept = delete; | ||
| 28 | |||
| 29 | void HandleProxyPacket(const ProxyPacket& packet); | ||
| 30 | |||
| 31 | Errno Initialize(Domain domain, Type type, Protocol socket_protocol) override; | ||
| 32 | |||
| 33 | Errno Close() override; | ||
| 34 | |||
| 35 | std::pair<AcceptResult, Errno> Accept() override; | ||
| 36 | |||
| 37 | Errno Connect(SockAddrIn addr_in) override; | ||
| 38 | |||
| 39 | std::pair<SockAddrIn, Errno> GetPeerName() override; | ||
| 40 | |||
| 41 | std::pair<SockAddrIn, Errno> GetSockName() override; | ||
| 42 | |||
| 43 | Errno Bind(SockAddrIn addr) override; | ||
| 44 | |||
| 45 | Errno Listen(s32 backlog) override; | ||
| 46 | |||
| 47 | Errno Shutdown(ShutdownHow how) override; | ||
| 48 | |||
| 49 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; | ||
| 50 | |||
| 51 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; | ||
| 52 | |||
| 53 | std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr, | ||
| 54 | std::size_t max_length); | ||
| 55 | |||
| 56 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; | ||
| 57 | |||
| 58 | void SendPacket(ProxyPacket& packet); | ||
| 59 | |||
| 60 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, | ||
| 61 | const SockAddrIn* addr) override; | ||
| 62 | |||
| 63 | Errno SetLinger(bool enable, u32 linger) override; | ||
| 64 | |||
| 65 | Errno SetReuseAddr(bool enable) override; | ||
| 66 | |||
| 67 | Errno SetBroadcast(bool enable) override; | ||
| 68 | |||
| 69 | Errno SetKeepAlive(bool enable) override; | ||
| 70 | |||
| 71 | Errno SetSndBuf(u32 value) override; | ||
| 72 | |||
| 73 | Errno SetRcvBuf(u32 value) override; | ||
| 74 | |||
| 75 | Errno SetSndTimeo(u32 value) override; | ||
| 76 | |||
| 77 | Errno SetRcvTimeo(u32 value) override; | ||
| 78 | |||
| 79 | Errno SetNonBlock(bool enable) override; | ||
| 80 | |||
| 81 | template <typename T> | ||
| 82 | Errno SetSockOpt(SOCKET fd, int option, T value); | ||
| 83 | |||
| 84 | bool IsOpened() const override; | ||
| 85 | |||
| 86 | bool broadcast = false; | ||
| 87 | bool closed = false; | ||
| 88 | u32 send_timeout = 0; | ||
| 89 | u32 receive_timeout = 0; | ||
| 90 | std::map<int, const char*> socket_options; | ||
| 91 | bool is_bound = false; | ||
| 92 | SockAddrIn local_endpoint{}; | ||
| 93 | bool blocking = true; | ||
| 94 | std::queue<ProxyPacket> received_packets; | ||
| 95 | Protocol protocol; | ||
| 96 | |||
| 97 | std::mutex packets_mutex; | ||
| 98 | |||
| 99 | RoomNetwork& room_network; | ||
| 100 | }; | ||
| 101 | |||
| 102 | } // namespace Network | ||
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 77e27e928..92dc49993 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h | |||
| @@ -14,20 +14,92 @@ | |||
| 14 | 14 | ||
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "core/internal_network/network.h" | 16 | #include "core/internal_network/network.h" |
| 17 | #include "network/network.h" | ||
| 17 | 18 | ||
| 18 | // TODO: C++20 Replace std::vector usages with std::span | 19 | // TODO: C++20 Replace std::vector usages with std::span |
| 19 | 20 | ||
| 20 | namespace Network { | 21 | namespace Network { |
| 21 | 22 | ||
| 22 | class Socket { | 23 | class SocketBase { |
| 23 | public: | 24 | public: |
| 25 | #ifdef YUZU_UNIX | ||
| 26 | using SOCKET = int; | ||
| 27 | static constexpr SOCKET INVALID_SOCKET = -1; | ||
| 28 | static constexpr SOCKET SOCKET_ERROR = -1; | ||
| 29 | #endif | ||
| 30 | |||
| 24 | struct AcceptResult { | 31 | struct AcceptResult { |
| 25 | std::unique_ptr<Socket> socket; | 32 | std::unique_ptr<SocketBase> socket; |
| 26 | SockAddrIn sockaddr_in; | 33 | SockAddrIn sockaddr_in; |
| 27 | }; | 34 | }; |
| 35 | virtual ~SocketBase() {} | ||
| 36 | |||
| 37 | virtual SocketBase& operator=(const SocketBase&) = delete; | ||
| 38 | |||
| 39 | // Avoid closing sockets implicitly | ||
| 40 | virtual SocketBase& operator=(SocketBase&&) noexcept = delete; | ||
| 41 | |||
| 42 | virtual Errno Initialize(Domain domain, Type type, Protocol protocol) = 0; | ||
| 43 | |||
| 44 | virtual Errno Close() = 0; | ||
| 45 | |||
| 46 | virtual std::pair<AcceptResult, Errno> Accept() = 0; | ||
| 47 | |||
| 48 | virtual Errno Connect(SockAddrIn addr_in) = 0; | ||
| 49 | |||
| 50 | virtual std::pair<SockAddrIn, Errno> GetPeerName() = 0; | ||
| 51 | |||
| 52 | virtual std::pair<SockAddrIn, Errno> GetSockName() = 0; | ||
| 53 | |||
| 54 | virtual Errno Bind(SockAddrIn addr) = 0; | ||
| 55 | |||
| 56 | virtual Errno Listen(s32 backlog) = 0; | ||
| 57 | |||
| 58 | virtual Errno Shutdown(ShutdownHow how) = 0; | ||
| 59 | |||
| 60 | virtual std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) = 0; | ||
| 61 | |||
| 62 | virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, | ||
| 63 | SockAddrIn* addr) = 0; | ||
| 64 | |||
| 65 | virtual std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) = 0; | ||
| 66 | |||
| 67 | virtual std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, | ||
| 68 | const SockAddrIn* addr) = 0; | ||
| 69 | |||
| 70 | virtual Errno SetLinger(bool enable, u32 linger) = 0; | ||
| 71 | |||
| 72 | virtual Errno SetReuseAddr(bool enable) = 0; | ||
| 73 | |||
| 74 | virtual Errno SetKeepAlive(bool enable) = 0; | ||
| 75 | |||
| 76 | virtual Errno SetBroadcast(bool enable) = 0; | ||
| 28 | 77 | ||
| 29 | explicit Socket() = default; | 78 | virtual Errno SetSndBuf(u32 value) = 0; |
| 30 | ~Socket(); | 79 | |
| 80 | virtual Errno SetRcvBuf(u32 value) = 0; | ||
| 81 | |||
| 82 | virtual Errno SetSndTimeo(u32 value) = 0; | ||
| 83 | |||
| 84 | virtual Errno SetRcvTimeo(u32 value) = 0; | ||
| 85 | |||
| 86 | virtual Errno SetNonBlock(bool enable) = 0; | ||
| 87 | |||
| 88 | virtual bool IsOpened() const = 0; | ||
| 89 | |||
| 90 | virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; | ||
| 91 | |||
| 92 | #if defined(_WIN32) | ||
| 93 | SOCKET fd = INVALID_SOCKET; | ||
| 94 | #elif YUZU_UNIX | ||
| 95 | int fd = -1; | ||
| 96 | #endif | ||
| 97 | }; | ||
| 98 | |||
| 99 | class Socket : public SocketBase { | ||
| 100 | public: | ||
| 101 | Socket() = default; | ||
| 102 | ~Socket() override; | ||
| 31 | 103 | ||
| 32 | Socket(const Socket&) = delete; | 104 | Socket(const Socket&) = delete; |
| 33 | Socket& operator=(const Socket&) = delete; | 105 | Socket& operator=(const Socket&) = delete; |
| @@ -37,57 +109,57 @@ public: | |||
| 37 | // Avoid closing sockets implicitly | 109 | // Avoid closing sockets implicitly |
| 38 | Socket& operator=(Socket&&) noexcept = delete; | 110 | Socket& operator=(Socket&&) noexcept = delete; |
| 39 | 111 | ||
| 40 | Errno Initialize(Domain domain, Type type, Protocol protocol); | 112 | Errno Initialize(Domain domain, Type type, Protocol protocol) override; |
| 41 | 113 | ||
| 42 | Errno Close(); | 114 | Errno Close() override; |
| 43 | 115 | ||
| 44 | std::pair<AcceptResult, Errno> Accept(); | 116 | std::pair<AcceptResult, Errno> Accept() override; |
| 45 | 117 | ||
| 46 | Errno Connect(SockAddrIn addr_in); | 118 | Errno Connect(SockAddrIn addr_in) override; |
| 47 | 119 | ||
| 48 | std::pair<SockAddrIn, Errno> GetPeerName(); | 120 | std::pair<SockAddrIn, Errno> GetPeerName() override; |
| 49 | 121 | ||
| 50 | std::pair<SockAddrIn, Errno> GetSockName(); | 122 | std::pair<SockAddrIn, Errno> GetSockName() override; |
| 51 | 123 | ||
| 52 | Errno Bind(SockAddrIn addr); | 124 | Errno Bind(SockAddrIn addr) override; |
| 53 | 125 | ||
| 54 | Errno Listen(s32 backlog); | 126 | Errno Listen(s32 backlog) override; |
| 55 | 127 | ||
| 56 | Errno Shutdown(ShutdownHow how); | 128 | Errno Shutdown(ShutdownHow how) override; |
| 57 | 129 | ||
| 58 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message); | 130 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; |
| 59 | 131 | ||
| 60 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr); | 132 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; |
| 61 | 133 | ||
| 62 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags); | 134 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; |
| 63 | 135 | ||
| 64 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, const SockAddrIn* addr); | 136 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, |
| 137 | const SockAddrIn* addr) override; | ||
| 65 | 138 | ||
| 66 | Errno SetLinger(bool enable, u32 linger); | 139 | Errno SetLinger(bool enable, u32 linger) override; |
| 67 | 140 | ||
| 68 | Errno SetReuseAddr(bool enable); | 141 | Errno SetReuseAddr(bool enable) override; |
| 69 | 142 | ||
| 70 | Errno SetKeepAlive(bool enable); | 143 | Errno SetKeepAlive(bool enable) override; |
| 71 | 144 | ||
| 72 | Errno SetBroadcast(bool enable); | 145 | Errno SetBroadcast(bool enable) override; |
| 73 | 146 | ||
| 74 | Errno SetSndBuf(u32 value); | 147 | Errno SetSndBuf(u32 value) override; |
| 75 | 148 | ||
| 76 | Errno SetRcvBuf(u32 value); | 149 | Errno SetRcvBuf(u32 value) override; |
| 77 | 150 | ||
| 78 | Errno SetSndTimeo(u32 value); | 151 | Errno SetSndTimeo(u32 value) override; |
| 79 | 152 | ||
| 80 | Errno SetRcvTimeo(u32 value); | 153 | Errno SetRcvTimeo(u32 value) override; |
| 81 | 154 | ||
| 82 | Errno SetNonBlock(bool enable); | 155 | Errno SetNonBlock(bool enable) override; |
| 83 | 156 | ||
| 84 | bool IsOpened() const; | 157 | template <typename T> |
| 158 | Errno SetSockOpt(SOCKET fd, int option, T value); | ||
| 85 | 159 | ||
| 86 | #if defined(_WIN32) | 160 | bool IsOpened() const override; |
| 87 | SOCKET fd = INVALID_SOCKET; | 161 | |
| 88 | #elif YUZU_UNIX | 162 | void HandleProxyPacket(const ProxyPacket& packet) override; |
| 89 | int fd = -1; | ||
| 90 | #endif | ||
| 91 | }; | 163 | }; |
| 92 | 164 | ||
| 93 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); | 165 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); |