2020-07-12 00:42:56 +00:00
|
|
|
// Copyright 2020 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <array>
|
2021-08-12 19:32:53 +00:00
|
|
|
#include <optional>
|
2020-07-12 00:42:56 +00:00
|
|
|
#include <utility>
|
|
|
|
|
[network] Error handling reform
`network.cpp` has several error paths which either:
- report "Unhandled host socket error=n" and return `SUCCESS`, or
- switch on a few possible errors, log them, and translate them to
Errno; the same switch statement is copied and pasted in multiple
places in the code
Convert these paths to use a helper function `GetAndLogLastError`, which
is roughly the equivalent of one of the switch statements, but:
- handling more cases (both ones that were already in `Errno`, and a few
more I added), and
- using OS functions to convert the error to a string when logging, so
it'll describe the error even if it's not one of the ones in the
switch statement.
- To handle this, refactor the logic in `GetLastErrorMsg` to expose a
new function `NativeErrorToString` which takes the error number
explicitly as an argument. And improve the Windows version a bit.
Also, add a test which exercises two random error paths.
2021-01-24 20:17:02 +00:00
|
|
|
#include "common/common_funcs.h"
|
2020-07-12 00:42:56 +00:00
|
|
|
#include "common/common_types.h"
|
|
|
|
|
2021-08-16 08:32:25 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <winsock2.h>
|
|
|
|
#elif YUZU_UNIX
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
2020-07-12 00:42:56 +00:00
|
|
|
namespace Network {
|
|
|
|
|
|
|
|
class Socket;
|
|
|
|
|
|
|
|
/// Error code for network functions
|
|
|
|
enum class Errno {
|
|
|
|
SUCCESS,
|
|
|
|
BADF,
|
|
|
|
INVAL,
|
|
|
|
MFILE,
|
|
|
|
NOTCONN,
|
|
|
|
AGAIN,
|
[network] Error handling reform
`network.cpp` has several error paths which either:
- report "Unhandled host socket error=n" and return `SUCCESS`, or
- switch on a few possible errors, log them, and translate them to
Errno; the same switch statement is copied and pasted in multiple
places in the code
Convert these paths to use a helper function `GetAndLogLastError`, which
is roughly the equivalent of one of the switch statements, but:
- handling more cases (both ones that were already in `Errno`, and a few
more I added), and
- using OS functions to convert the error to a string when logging, so
it'll describe the error even if it's not one of the ones in the
switch statement.
- To handle this, refactor the logic in `GetLastErrorMsg` to expose a
new function `NativeErrorToString` which takes the error number
explicitly as an argument. And improve the Windows version a bit.
Also, add a test which exercises two random error paths.
2021-01-24 20:17:02 +00:00
|
|
|
CONNREFUSED,
|
|
|
|
HOSTUNREACH,
|
|
|
|
NETDOWN,
|
|
|
|
NETUNREACH,
|
|
|
|
OTHER,
|
2020-07-12 00:42:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Address families
|
|
|
|
enum class Domain {
|
|
|
|
INET, ///< Address family for IPv4
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Socket types
|
|
|
|
enum class Type {
|
|
|
|
STREAM,
|
|
|
|
DGRAM,
|
|
|
|
RAW,
|
|
|
|
SEQPACKET,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Protocol values for sockets
|
|
|
|
enum class Protocol {
|
|
|
|
ICMP,
|
|
|
|
TCP,
|
|
|
|
UDP,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Shutdown mode
|
|
|
|
enum class ShutdownHow {
|
|
|
|
RD,
|
|
|
|
WR,
|
|
|
|
RDWR,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Array of IPv4 address
|
|
|
|
using IPv4Address = std::array<u8, 4>;
|
|
|
|
|
|
|
|
/// Cross-platform sockaddr structure
|
|
|
|
struct SockAddrIn {
|
|
|
|
Domain family;
|
|
|
|
IPv4Address ip;
|
|
|
|
u16 portno;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Cross-platform poll fd structure
|
network, sockets: Replace `POLL_IN`, `POLL_OUT`, etc. constants with an `enum class PollEvents`
Actually, two enum classes, since for some reason there are two separate
yet identical `PollFD` types used in the codebase. I get that one is
ABI-compatible with the Switch while the other is an abstract type used
for the host, but why not use `WSAPOLLFD` directly for the latter?
Anyway, why make this change? Because on Apple platforms, `POLL_IN`,
`POLL_OUT`, etc. (with an underscore) are defined as macros in
<sys/signal.h>. (This is inherited from FreeBSD.) So defining
a variable with the same name causes a compile error.
I could just rename the variables, but while I was at it I thought I
might as well switch to an enum for stronger typing.
Also, change the type used for values copied directly to/from the
`events` and `revents` fields of the host *native*
`pollfd`/`WSASPOLLFD`, from `u32` to `short`, as `short` is the correct
canonical type on both Unix and Windows.
2020-08-31 14:20:44 +00:00
|
|
|
|
|
|
|
enum class PollEvents : u16 {
|
|
|
|
// Using Pascal case because IN is a macro on Windows.
|
|
|
|
In = 1 << 0,
|
|
|
|
Pri = 1 << 1,
|
|
|
|
Out = 1 << 2,
|
|
|
|
Err = 1 << 3,
|
|
|
|
Hup = 1 << 4,
|
|
|
|
Nval = 1 << 5,
|
|
|
|
};
|
|
|
|
|
|
|
|
DECLARE_ENUM_FLAG_OPERATORS(PollEvents);
|
|
|
|
|
2020-07-12 00:42:56 +00:00
|
|
|
struct PollFD {
|
|
|
|
Socket* socket;
|
network, sockets: Replace `POLL_IN`, `POLL_OUT`, etc. constants with an `enum class PollEvents`
Actually, two enum classes, since for some reason there are two separate
yet identical `PollFD` types used in the codebase. I get that one is
ABI-compatible with the Switch while the other is an abstract type used
for the host, but why not use `WSAPOLLFD` directly for the latter?
Anyway, why make this change? Because on Apple platforms, `POLL_IN`,
`POLL_OUT`, etc. (with an underscore) are defined as macros in
<sys/signal.h>. (This is inherited from FreeBSD.) So defining
a variable with the same name causes a compile error.
I could just rename the variables, but while I was at it I thought I
might as well switch to an enum for stronger typing.
Also, change the type used for values copied directly to/from the
`events` and `revents` fields of the host *native*
`pollfd`/`WSASPOLLFD`, from `u32` to `short`, as `short` is the correct
canonical type on both Unix and Windows.
2020-08-31 14:20:44 +00:00
|
|
|
PollEvents events;
|
|
|
|
PollEvents revents;
|
2020-07-12 00:42:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class NetworkInstance {
|
|
|
|
public:
|
|
|
|
explicit NetworkInstance();
|
|
|
|
~NetworkInstance();
|
|
|
|
};
|
|
|
|
|
2021-08-16 08:32:25 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
constexpr IPv4Address TranslateIPv4(in_addr addr) {
|
|
|
|
auto& bytes = addr.S_un.S_un_b;
|
|
|
|
return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4};
|
|
|
|
}
|
|
|
|
#elif YUZU_UNIX
|
|
|
|
constexpr IPv4Address TranslateIPv4(in_addr addr) {
|
|
|
|
const u32 bytes = addr.s_addr;
|
|
|
|
return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8),
|
|
|
|
static_cast<u8>(bytes >> 16), static_cast<u8>(bytes >> 24)};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-07-12 00:42:56 +00:00
|
|
|
/// @brief Returns host's IPv4 address
|
2021-08-12 19:32:53 +00:00
|
|
|
/// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array
|
|
|
|
std::optional<IPv4Address> GetHostIPv4Address();
|
2020-07-12 00:42:56 +00:00
|
|
|
|
|
|
|
} // namespace Network
|