forked from etc/pineapple-src
early-access version 1493
This commit is contained in:
parent
889b7ee921
commit
99783aa746
11 changed files with 171 additions and 131 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1492.
|
This is the source code for early-access 1493.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,13 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||||
// Generic function to get last error message.
|
// Generic function to get last error message.
|
||||||
// Call directly after the command or use the error num.
|
// Call directly after the command or use the error num.
|
||||||
// This function might change the error code.
|
// This function might change the error code.
|
||||||
// Defined in Misc.cpp.
|
// Defined in misc.cpp.
|
||||||
[[nodiscard]] std::string GetLastErrorMsg();
|
[[nodiscard]] std::string GetLastErrorMsg();
|
||||||
|
|
||||||
|
// Like GetLastErrorMsg(), but passing an explicit error code.
|
||||||
|
// Defined in misc.cpp.
|
||||||
|
[[nodiscard]] std::string NativeErrorToString(int e);
|
||||||
|
|
||||||
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
|
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
|
||||||
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
|
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
|
|
|
@ -12,27 +12,41 @@
|
||||||
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
|
|
||||||
// Generic function to get last error message.
|
std::string NativeErrorToString(int e) {
|
||||||
// Call directly after the command or use the error num.
|
|
||||||
// This function might change the error code.
|
|
||||||
std::string GetLastErrorMsg() {
|
|
||||||
static constexpr std::size_t buff_size = 255;
|
|
||||||
char err_str[buff_size];
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
|
LPSTR err_str;
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr);
|
|
||||||
return std::string(err_str, buff_size);
|
DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
#elif defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
|
||||||
|
if (!res) {
|
||||||
|
return "(FormatMessageA failed to format error)";
|
||||||
|
}
|
||||||
|
std::string ret(err_str);
|
||||||
|
LocalFree(err_str);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
char err_str[255];
|
||||||
|
#if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
|
||||||
// Thread safe (GNU-specific)
|
// Thread safe (GNU-specific)
|
||||||
const char* str = strerror_r(errno, err_str, buff_size);
|
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
||||||
return std::string(str);
|
return std::string(str);
|
||||||
#else
|
#else
|
||||||
// Thread safe (XSI-compliant)
|
// Thread safe (XSI-compliant)
|
||||||
const int success = strerror_r(errno, err_str, buff_size);
|
int second_err = strerror_r(e, err_str, sizeof(err_str));
|
||||||
if (success != 0) {
|
if (second_err != 0) {
|
||||||
return {};
|
return "(strerror_r failed to format error)";
|
||||||
}
|
}
|
||||||
return std::string(err_str);
|
return std::string(err_str);
|
||||||
|
#endif // GLIBC etc.
|
||||||
|
#endif // _WIN32
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetLastErrorMsg() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return NativeErrorToString(GetLastError());
|
||||||
|
#else
|
||||||
|
return NativeErrorToString(errno);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
|
||||||
|
@ -90,15 +91,36 @@ LINGER MakeLinger(bool enable, u32 linger_value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LastError() {
|
|
||||||
return WSAGetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EnableNonBlock(SOCKET fd, bool enable) {
|
bool EnableNonBlock(SOCKET fd, bool enable) {
|
||||||
u_long value = enable ? 1 : 0;
|
u_long value = enable ? 1 : 0;
|
||||||
return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
|
return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Errno TranslateNativeError(int e) {
|
||||||
|
switch (e) {
|
||||||
|
case WSAEBADF:
|
||||||
|
return Errno::BADF;
|
||||||
|
case WSAEINVAL:
|
||||||
|
return Errno::INVAL;
|
||||||
|
case WSAEMFILE:
|
||||||
|
return Errno::MFILE;
|
||||||
|
case WSAENOTCONN:
|
||||||
|
return Errno::NOTCONN;
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
return Errno::AGAIN;
|
||||||
|
case WSAECONNREFUSED:
|
||||||
|
return Errno::CONNREFUSED;
|
||||||
|
case WSAEHOSTUNREACH:
|
||||||
|
return Errno::HOSTUNREACH;
|
||||||
|
case WSAENETDOWN:
|
||||||
|
return Errno::NETDOWN;
|
||||||
|
case WSAENETUNREACH:
|
||||||
|
return Errno::NETUNREACH;
|
||||||
|
default:
|
||||||
|
return Errno::OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX
|
#elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX
|
||||||
|
|
||||||
using SOCKET = int;
|
using SOCKET = int;
|
||||||
|
@ -108,9 +130,6 @@ using ULONG = u64;
|
||||||
constexpr SOCKET INVALID_SOCKET = -1;
|
constexpr SOCKET INVALID_SOCKET = -1;
|
||||||
constexpr SOCKET SOCKET_ERROR = -1;
|
constexpr SOCKET SOCKET_ERROR = -1;
|
||||||
|
|
||||||
constexpr int WSAEWOULDBLOCK = EAGAIN;
|
|
||||||
constexpr int WSAENOTCONN = ENOTCONN;
|
|
||||||
|
|
||||||
constexpr int SD_RECEIVE = SHUT_RD;
|
constexpr int SD_RECEIVE = SHUT_RD;
|
||||||
constexpr int SD_SEND = SHUT_WR;
|
constexpr int SD_SEND = SHUT_WR;
|
||||||
constexpr int SD_BOTH = SHUT_RDWR;
|
constexpr int SD_BOTH = SHUT_RDWR;
|
||||||
|
@ -162,10 +181,6 @@ linger MakeLinger(bool enable, u32 linger_value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LastError() {
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EnableNonBlock(int fd, bool enable) {
|
bool EnableNonBlock(int fd, bool enable) {
|
||||||
int flags = fcntl(fd, F_GETFD);
|
int flags = fcntl(fd, F_GETFD);
|
||||||
if (flags == -1) {
|
if (flags == -1) {
|
||||||
|
@ -179,8 +194,43 @@ bool EnableNonBlock(int fd, bool enable) {
|
||||||
return fcntl(fd, F_SETFD, flags) == 0;
|
return fcntl(fd, F_SETFD, flags) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Errno TranslateNativeError(int e) {
|
||||||
|
switch (e) {
|
||||||
|
case EBADF:
|
||||||
|
return Errno::BADF;
|
||||||
|
case EINVAL:
|
||||||
|
return Errno::INVAL;
|
||||||
|
case EMFILE:
|
||||||
|
return Errno::MFILE;
|
||||||
|
case ENOTCONN:
|
||||||
|
return Errno::NOTCONN;
|
||||||
|
case EAGAIN:
|
||||||
|
return Errno::AGAIN;
|
||||||
|
case ECONNREFUSED:
|
||||||
|
return Errno::CONNREFUSED;
|
||||||
|
case EHOSTUNREACH:
|
||||||
|
return Errno::HOSTUNREACH;
|
||||||
|
case ENETDOWN:
|
||||||
|
return Errno::NETDOWN;
|
||||||
|
case ENETUNREACH:
|
||||||
|
return Errno::NETUNREACH;
|
||||||
|
default:
|
||||||
|
return Errno::OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Errno GetAndLogLastError() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
int e = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
int e = errno;
|
||||||
|
#endif
|
||||||
|
LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e));
|
||||||
|
return TranslateNativeError(e);
|
||||||
|
}
|
||||||
|
|
||||||
int TranslateDomain(Domain domain) {
|
int TranslateDomain(Domain domain) {
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
case Domain::INET:
|
case Domain::INET:
|
||||||
|
@ -290,9 +340,7 @@ Errno SetSockOpt(SOCKET fd, int option, T value) {
|
||||||
if (result != SOCKET_ERROR) {
|
if (result != SOCKET_ERROR) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
const int ec = LastError();
|
return GetAndLogLastError();
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
@ -308,14 +356,12 @@ NetworkInstance::~NetworkInstance() {
|
||||||
std::pair<IPv4Address, Errno> GetHostIPv4Address() {
|
std::pair<IPv4Address, Errno> GetHostIPv4Address() {
|
||||||
std::array<char, 256> name{};
|
std::array<char, 256> name{};
|
||||||
if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) {
|
if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) {
|
||||||
UNIMPLEMENTED_MSG("Unhandled gethostname error");
|
return {IPv4Address{}, GetAndLogLastError()};
|
||||||
return {IPv4Address{}, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hostent* const ent = gethostbyname(name.data());
|
hostent* const ent = gethostbyname(name.data());
|
||||||
if (!ent) {
|
if (!ent) {
|
||||||
UNIMPLEMENTED_MSG("Unhandled gethostbyname error");
|
return {IPv4Address{}, GetAndLogLastError()};
|
||||||
return {IPv4Address{}, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
if (ent->h_addr_list == nullptr) {
|
if (ent->h_addr_list == nullptr) {
|
||||||
UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
|
UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
|
||||||
|
@ -359,9 +405,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
|
||||||
|
|
||||||
ASSERT(result == SOCKET_ERROR);
|
ASSERT(result == SOCKET_ERROR);
|
||||||
|
|
||||||
const int ec = LastError();
|
return {-1, GetAndLogLastError()};
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {-1, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket::~Socket() {
|
Socket::~Socket() {
|
||||||
|
@ -380,9 +424,7 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ec = LastError();
|
return GetAndLogLastError();
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
|
std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
|
||||||
|
@ -391,9 +433,7 @@ std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
|
||||||
const SOCKET new_socket = accept(fd, &addr, &addrlen);
|
const SOCKET new_socket = accept(fd, &addr, &addrlen);
|
||||||
|
|
||||||
if (new_socket == INVALID_SOCKET) {
|
if (new_socket == INVALID_SOCKET) {
|
||||||
const int ec = LastError();
|
return {AcceptResult{}, GetAndLogLastError()};
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {AcceptResult{}, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AcceptResult result;
|
AcceptResult result;
|
||||||
|
@ -412,23 +452,14 @@ Errno Socket::Connect(SockAddrIn addr_in) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (const int ec = LastError()) {
|
return GetAndLogLastError();
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
LOG_DEBUG(Service, "EAGAIN generated");
|
|
||||||
return Errno::AGAIN;
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SockAddrIn, Errno> Socket::GetPeerName() {
|
std::pair<SockAddrIn, Errno> Socket::GetPeerName() {
|
||||||
sockaddr addr;
|
sockaddr addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) {
|
if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) {
|
||||||
const int ec = LastError();
|
return {SockAddrIn{}, GetAndLogLastError()};
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {SockAddrIn{}, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(addrlen == sizeof(sockaddr_in));
|
ASSERT(addrlen == sizeof(sockaddr_in));
|
||||||
|
@ -439,9 +470,7 @@ std::pair<SockAddrIn, Errno> Socket::GetSockName() {
|
||||||
sockaddr addr;
|
sockaddr addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) {
|
if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) {
|
||||||
const int ec = LastError();
|
return {SockAddrIn{}, GetAndLogLastError()};
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {SockAddrIn{}, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(addrlen == sizeof(sockaddr_in));
|
ASSERT(addrlen == sizeof(sockaddr_in));
|
||||||
|
@ -454,9 +483,7 @@ Errno Socket::Bind(SockAddrIn addr) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ec = LastError();
|
return GetAndLogLastError();
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Errno Socket::Listen(s32 backlog) {
|
Errno Socket::Listen(s32 backlog) {
|
||||||
|
@ -464,9 +491,7 @@ Errno Socket::Listen(s32 backlog) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ec = LastError();
|
return GetAndLogLastError();
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Errno Socket::Shutdown(ShutdownHow how) {
|
Errno Socket::Shutdown(ShutdownHow how) {
|
||||||
|
@ -489,14 +514,7 @@ Errno Socket::Shutdown(ShutdownHow how) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (const int ec = LastError()) {
|
return GetAndLogLastError();
|
||||||
case WSAENOTCONN:
|
|
||||||
LOG_ERROR(Service, "ENOTCONN generated");
|
|
||||||
return Errno::NOTCONN;
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
|
std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
|
||||||
|
@ -509,17 +527,7 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
|
||||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (const int ec = LastError()) {
|
return {-1, GetAndLogLastError()};
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
LOG_DEBUG(Service, "EAGAIN generated");
|
|
||||||
return {-1, Errno::AGAIN};
|
|
||||||
case WSAENOTCONN:
|
|
||||||
LOG_ERROR(Service, "ENOTCONN generated");
|
|
||||||
return {-1, Errno::NOTCONN};
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {0, Errno::SUCCESS};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) {
|
std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) {
|
||||||
|
@ -541,17 +549,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
|
||||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (const int ec = LastError()) {
|
return {-1, GetAndLogLastError()};
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
LOG_DEBUG(Service, "EAGAIN generated");
|
|
||||||
return {-1, Errno::AGAIN};
|
|
||||||
case WSAENOTCONN:
|
|
||||||
LOG_ERROR(Service, "ENOTCONN generated");
|
|
||||||
return {-1, Errno::NOTCONN};
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {-1, Errno::SUCCESS};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
|
std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
|
||||||
|
@ -564,18 +562,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
|
||||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ec = LastError();
|
return {-1, GetAndLogLastError()};
|
||||||
switch (ec) {
|
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
LOG_DEBUG(Service, "EAGAIN generated");
|
|
||||||
return {-1, Errno::AGAIN};
|
|
||||||
case WSAENOTCONN:
|
|
||||||
LOG_ERROR(Service, "ENOTCONN generated");
|
|
||||||
return {-1, Errno::NOTCONN};
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {-1, Errno::SUCCESS};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
|
std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
|
||||||
|
@ -597,9 +584,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
|
||||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ec = LastError();
|
return {-1, GetAndLogLastError()};
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return {-1, Errno::SUCCESS};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Errno Socket::Close() {
|
Errno Socket::Close() {
|
||||||
|
@ -642,9 +627,7 @@ Errno Socket::SetNonBlock(bool enable) {
|
||||||
if (EnableNonBlock(fd, enable)) {
|
if (EnableNonBlock(fd, enable)) {
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
const int ec = LastError();
|
return GetAndLogLastError();
|
||||||
UNREACHABLE_MSG("Unhandled host socket error={}", ec);
|
|
||||||
return Errno::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::IsOpened() const {
|
bool Socket::IsOpened() const {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Network {
|
namespace Network {
|
||||||
|
@ -21,6 +22,11 @@ enum class Errno {
|
||||||
MFILE,
|
MFILE,
|
||||||
NOTCONN,
|
NOTCONN,
|
||||||
AGAIN,
|
AGAIN,
|
||||||
|
CONNREFUSED,
|
||||||
|
HOSTUNREACH,
|
||||||
|
NETDOWN,
|
||||||
|
NETUNREACH,
|
||||||
|
OTHER,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Address families
|
/// Address families
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <random>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -26,10 +27,10 @@ class Socket {
|
||||||
public:
|
public:
|
||||||
using clock = std::chrono::system_clock;
|
using clock = std::chrono::system_clock;
|
||||||
|
|
||||||
explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, u32 client_id_,
|
explicit Socket(const std::string& host, u16 port, std::size_t pad_index_,
|
||||||
SocketCallback callback_)
|
SocketCallback callback_)
|
||||||
: callback(std::move(callback_)), timer(io_service),
|
: callback(std::move(callback_)), timer(io_service),
|
||||||
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id_),
|
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()),
|
||||||
pad_index(pad_index_) {
|
pad_index(pad_index_) {
|
||||||
boost::system::error_code ec{};
|
boost::system::error_code ec{};
|
||||||
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
|
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
|
||||||
|
@ -63,6 +64,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
u32 GenerateRandomClientId() const {
|
||||||
|
std::random_device device;
|
||||||
|
return device();
|
||||||
|
}
|
||||||
|
|
||||||
void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
|
void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
|
||||||
if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
|
if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
|
||||||
switch (*type) {
|
switch (*type) {
|
||||||
|
@ -115,7 +121,7 @@ private:
|
||||||
boost::asio::basic_waitable_timer<clock> timer;
|
boost::asio::basic_waitable_timer<clock> timer;
|
||||||
udp::socket socket;
|
udp::socket socket;
|
||||||
|
|
||||||
u32 client_id{};
|
const u32 client_id;
|
||||||
std::size_t pad_index{};
|
std::size_t pad_index{};
|
||||||
|
|
||||||
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
|
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
|
||||||
|
@ -203,7 +209,7 @@ void Client::ReloadSockets() {
|
||||||
LOG_ERROR(Input, "Duplicated UDP servers found");
|
LOG_ERROR(Input, "Duplicated UDP servers found");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
StartCommunication(client++, udp_input_address, udp_input_port, pad, 24872);
|
StartCommunication(client++, udp_input_address, udp_input_port, pad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +283,7 @@ void Client::OnPadData(Response::PadData data, std::size_t client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::StartCommunication(std::size_t client, const std::string& host, u16 port,
|
void Client::StartCommunication(std::size_t client, const std::string& host, u16 port,
|
||||||
std::size_t pad_index, u32 client_id) {
|
std::size_t pad_index) {
|
||||||
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
|
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
|
||||||
[this](Response::PortInfo info) { OnPortInfo(info); },
|
[this](Response::PortInfo info) { OnPortInfo(info); },
|
||||||
[this, client](Response::PadData data) { OnPadData(data, client); }};
|
[this, client](Response::PadData data) { OnPadData(data, client); }};
|
||||||
|
@ -287,7 +293,7 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
|
||||||
clients[client].port = port;
|
clients[client].port = port;
|
||||||
clients[client].pad_index = pad_index;
|
clients[client].pad_index = pad_index;
|
||||||
clients[client].active = 0;
|
clients[client].active = 0;
|
||||||
clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
|
clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback);
|
||||||
clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
|
clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
|
||||||
// Set motion parameters
|
// Set motion parameters
|
||||||
// SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
|
// SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
|
||||||
|
@ -416,7 +422,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
|
||||||
return pad_queue;
|
return pad_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
|
void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
|
||||||
const std::function<void()>& success_callback,
|
const std::function<void()>& success_callback,
|
||||||
const std::function<void()>& failure_callback) {
|
const std::function<void()>& failure_callback) {
|
||||||
std::thread([=] {
|
std::thread([=] {
|
||||||
|
@ -426,7 +432,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
|
||||||
.port_info = [](Response::PortInfo) {},
|
.port_info = [](Response::PortInfo) {},
|
||||||
.pad_data = [&](Response::PadData) { success_event.Set(); },
|
.pad_data = [&](Response::PadData) { success_event.Set(); },
|
||||||
};
|
};
|
||||||
Socket socket{host, port, pad_index, client_id, std::move(callback)};
|
Socket socket{host, port, pad_index, std::move(callback)};
|
||||||
std::thread worker_thread{SocketLoop, &socket};
|
std::thread worker_thread{SocketLoop, &socket};
|
||||||
const bool result = success_event.WaitFor(std::chrono::seconds(5));
|
const bool result = success_event.WaitFor(std::chrono::seconds(5));
|
||||||
socket.Stop();
|
socket.Stop();
|
||||||
|
@ -440,7 +446,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||||
const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
|
const std::string& host, u16 port, std::size_t pad_index,
|
||||||
std::function<void(Status)> status_callback,
|
std::function<void(Status)> status_callback,
|
||||||
std::function<void(u16, u16, u16, u16)> data_callback) {
|
std::function<void(u16, u16, u16, u16)> data_callback) {
|
||||||
|
|
||||||
|
@ -485,7 +491,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||||
complete_event.Set();
|
complete_event.Set();
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
Socket socket{host, port, pad_index, client_id, std::move(callback)};
|
Socket socket{host, port, pad_index, std::move(callback)};
|
||||||
std::thread worker_thread{SocketLoop, &socket};
|
std::thread worker_thread{SocketLoop, &socket};
|
||||||
complete_event.Wait();
|
complete_event.Wait();
|
||||||
socket.Stop();
|
socket.Stop();
|
||||||
|
|
|
@ -126,7 +126,7 @@ private:
|
||||||
void OnPortInfo(Response::PortInfo);
|
void OnPortInfo(Response::PortInfo);
|
||||||
void OnPadData(Response::PadData, std::size_t client);
|
void OnPadData(Response::PadData, std::size_t client);
|
||||||
void StartCommunication(std::size_t client, const std::string& host, u16 port,
|
void StartCommunication(std::size_t client, const std::string& host, u16 port,
|
||||||
std::size_t pad_index, u32 client_id);
|
std::size_t pad_index);
|
||||||
void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
|
void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
|
||||||
const Common::Vec3<float>& gyro);
|
const Common::Vec3<float>& gyro);
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ public:
|
||||||
* @param data_callback Called when calibration data is ready
|
* @param data_callback Called when calibration data is ready
|
||||||
*/
|
*/
|
||||||
explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index,
|
explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index,
|
||||||
u32 client_id, std::function<void(Status)> status_callback,
|
std::function<void(Status)> status_callback,
|
||||||
std::function<void(u16, u16, u16, u16)> data_callback);
|
std::function<void(u16, u16, u16, u16)> data_callback);
|
||||||
~CalibrationConfigurationJob();
|
~CalibrationConfigurationJob();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
@ -174,7 +174,7 @@ private:
|
||||||
Common::Event complete_event;
|
Common::Event complete_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id,
|
void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
|
||||||
const std::function<void()>& success_callback,
|
const std::function<void()>& success_callback,
|
||||||
const std::function<void()>& failure_callback);
|
const std::function<void()>& failure_callback);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ add_executable(tests
|
||||||
common/param_package.cpp
|
common/param_package.cpp
|
||||||
common/ring_buffer.cpp
|
common/ring_buffer.cpp
|
||||||
core/core_timing.cpp
|
core/core_timing.cpp
|
||||||
|
core/network/network.cpp
|
||||||
tests.cpp
|
tests.cpp
|
||||||
video_core/buffer_base.cpp
|
video_core/buffer_base.cpp
|
||||||
)
|
)
|
||||||
|
|
28
src/tests/core/network/network.cpp
Executable file
28
src/tests/core/network/network.cpp
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include "core/network/network.h"
|
||||||
|
#include "core/network/sockets.h"
|
||||||
|
|
||||||
|
TEST_CASE("Network::Errors", "[core]") {
|
||||||
|
Network::NetworkInstance network_instance; // initialize network
|
||||||
|
|
||||||
|
Network::Socket socks[2];
|
||||||
|
for (Network::Socket& sock : socks) {
|
||||||
|
REQUIRE(sock.Initialize(Network::Domain::INET, Network::Type::STREAM,
|
||||||
|
Network::Protocol::TCP) == Network::Errno::SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
Network::SockAddrIn addr{
|
||||||
|
Network::Domain::INET,
|
||||||
|
{127, 0, 0, 1},
|
||||||
|
1, // hopefully nobody running this test has something listening on port 1
|
||||||
|
};
|
||||||
|
REQUIRE(socks[0].Connect(addr) == Network::Errno::CONNREFUSED);
|
||||||
|
|
||||||
|
std::vector<u8> message{1, 2, 3, 4};
|
||||||
|
REQUIRE(socks[1].Recv(0, message).second == Network::Errno::NOTCONN);
|
||||||
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
|
CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
|
||||||
const std::string& host, u16 port,
|
const std::string& host, u16 port,
|
||||||
u8 pad_index, u16 client_id)
|
u8 pad_index)
|
||||||
: QDialog(parent) {
|
: QDialog(parent) {
|
||||||
layout = new QVBoxLayout;
|
layout = new QVBoxLayout;
|
||||||
status_label = new QLabel(tr("Communicating with the server..."));
|
status_label = new QLabel(tr("Communicating with the server..."));
|
||||||
|
@ -41,7 +41,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
|
||||||
|
|
||||||
using namespace InputCommon::CemuhookUDP;
|
using namespace InputCommon::CemuhookUDP;
|
||||||
job = std::make_unique<CalibrationConfigurationJob>(
|
job = std::make_unique<CalibrationConfigurationJob>(
|
||||||
host, port, pad_index, client_id,
|
host, port, pad_index,
|
||||||
[this](CalibrationConfigurationJob::Status status) {
|
[this](CalibrationConfigurationJob::Status status) {
|
||||||
QString text;
|
QString text;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -218,7 +218,6 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
|
||||||
udp_test_in_progress = true;
|
udp_test_in_progress = true;
|
||||||
InputCommon::CemuhookUDP::TestCommunication(
|
InputCommon::CemuhookUDP::TestCommunication(
|
||||||
ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0,
|
ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0,
|
||||||
24872,
|
|
||||||
[this] {
|
[this] {
|
||||||
LOG_INFO(Frontend, "UDP input test success");
|
LOG_INFO(Frontend, "UDP input test success");
|
||||||
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
|
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
|
||||||
|
@ -233,8 +232,7 @@ void ConfigureMotionTouch::OnConfigureTouchCalibration() {
|
||||||
ui->touch_calibration_config->setEnabled(false);
|
ui->touch_calibration_config->setEnabled(false);
|
||||||
ui->touch_calibration_config->setText(tr("Configuring"));
|
ui->touch_calibration_config->setText(tr("Configuring"));
|
||||||
CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(),
|
CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(),
|
||||||
static_cast<u16>(ui->udp_port->text().toUInt()), 0,
|
static_cast<u16>(ui->udp_port->text().toUInt()), 0);
|
||||||
24872);
|
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
if (dialog.completed) {
|
if (dialog.completed) {
|
||||||
min_x = dialog.min_x;
|
min_x = dialog.min_x;
|
||||||
|
|
|
@ -30,7 +30,7 @@ class CalibrationConfigurationDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port,
|
explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port,
|
||||||
u8 pad_index, u16 client_id);
|
u8 pad_index);
|
||||||
~CalibrationConfigurationDialog() override;
|
~CalibrationConfigurationDialog() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue