Implement some missing SOC functionality (#7176)

* Implement some missing SOC functionality

* Add LOG_POLL macro for debugging

* Fix compilation

* Temporary fix for Android

* Temporary fix for Android (for real)

* Apply suggestions

* Add stubbed notice to android sockatmark

* Apply suggestions
This commit is contained in:
PabloMK7 2023-12-17 17:50:24 +01:00 committed by GitHub
parent 2b20082581
commit d680b79725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 677 additions and 315 deletions

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,10 @@ namespace Core {
class System; class System;
} }
namespace IPC {
class RequestParser;
}
namespace Service::SOC { namespace Service::SOC {
/// Holds information about a particular socket /// Holds information about a particular socket
@ -26,12 +30,18 @@ struct SocketHolder {
#endif // _WIN32 #endif // _WIN32
bool blocking = true; ///< Whether the socket is blocking or not. bool blocking = true; ///< Whether the socket is blocking or not.
bool isGlobal = false;
bool shutdown_rd = false;
u32 ownerProcess = 0;
private: private:
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int) {
ar& socket_fd; ar& socket_fd;
ar& blocking; ar& blocking;
ar& isGlobal;
ar& ownerProcess;
} }
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
@ -51,9 +61,15 @@ public:
std::optional<InterfaceInfo> GetDefaultInterfaceInfo(); std::optional<InterfaceInfo> GetDefaultInterfaceInfo();
private: private:
static constexpr ResultCode ERR_INVALID_HANDLE = static constexpr ResultCode ERR_WRONG_PROCESS =
ResultCode(ErrorDescription::InvalidHandle, ErrorModule::SOC, ErrorSummary::InvalidArgument, ResultCode(4, ErrorModule::SOC, ErrorSummary::InvalidState, ErrorLevel::Status);
ErrorLevel::Permanent); static constexpr ResultCode ERR_NOT_INITIALIZED =
ResultCode(6, ErrorModule::SOC, ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
static constexpr ResultCode ERR_INVALID_SOCKET_DESCRIPTOR =
ResultCode(7, ErrorModule::SOC, ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
static constexpr ResultCode ERR_ALREADY_INITIALIZED =
ResultCode(11, ErrorModule::SOC, ErrorSummary::InvalidState, ErrorLevel::Status);
static constexpr u32 SOC_ERR_INAVLID_ENUM_VALUE = 0xFFFF8025; static constexpr u32 SOC_ERR_INAVLID_ENUM_VALUE = 0xFFFF8025;
static constexpr u32 SOC_SOL_IP = 0x0000; static constexpr u32 SOC_SOL_IP = 0x0000;
@ -70,6 +86,19 @@ private:
bool GetSocketBlocking(const SocketHolder& socket_holder); bool GetSocketBlocking(const SocketHolder& socket_holder);
u32 SetSocketBlocking(SocketHolder& socket_holder, bool blocking); u32 SetSocketBlocking(SocketHolder& socket_holder, bool blocking);
std::optional<std::reference_wrapper<SocketHolder>> GetSocketHolder(u32 ctr_socket_fd,
u32 process_id,
IPC::RequestParser& rp);
// Close and delete all sockets, optinally only the ones owned by the
// specified process ID.
void CloseAndDeleteAllSockets(s32 process_id = -1);
s32 SendToImpl(SocketHolder& holder, u32 len, u32 flags, u32 addr_len,
const std::vector<u8>& input_buff, const u8* dest_addr_buff);
static void RecvBusyWaitForEvent(SocketHolder& holder);
// From // From
// https://github.com/devkitPro/libctru/blob/1de86ea38aec419744149daf692556e187d4678a/libctru/include/3ds/services/soc.h#L15 // https://github.com/devkitPro/libctru/blob/1de86ea38aec419744149daf692556e187d4678a/libctru/include/3ds/services/soc.h#L15
enum class NetworkOpt { enum class NetworkOpt {
@ -86,33 +115,22 @@ private:
NETOPT_DHCP_LEASE_TIME = 0xC001, ///< The DHCP lease time remaining, in seconds NETOPT_DHCP_LEASE_TIME = 0xC001, ///< The DHCP lease time remaining, in seconds
}; };
struct HostByNameData {
static const u32 max_entries = 24;
u16_le addr_type;
u16_le addr_len;
u16_le addr_count;
u16_le alias_count;
std::array<char, 256> h_name;
std::array<std::array<char, 256>, max_entries> aliases;
std::array<std::array<u8, 16>, max_entries> addresses;
};
static_assert(sizeof(HostByNameData) == 0x1A88, "Invalid HostByNameData size");
void Socket(Kernel::HLERequestContext& ctx); void Socket(Kernel::HLERequestContext& ctx);
void Bind(Kernel::HLERequestContext& ctx); void Bind(Kernel::HLERequestContext& ctx);
void Fcntl(Kernel::HLERequestContext& ctx); void Fcntl(Kernel::HLERequestContext& ctx);
void Listen(Kernel::HLERequestContext& ctx); void Listen(Kernel::HLERequestContext& ctx);
void Accept(Kernel::HLERequestContext& ctx); void Accept(Kernel::HLERequestContext& ctx);
void SockAtMark(Kernel::HLERequestContext& ctx);
void GetHostId(Kernel::HLERequestContext& ctx); void GetHostId(Kernel::HLERequestContext& ctx);
void Close(Kernel::HLERequestContext& ctx); void Close(Kernel::HLERequestContext& ctx);
void SendToOther(Kernel::HLERequestContext& ctx); void SendToOther(Kernel::HLERequestContext& ctx);
void SendTo(Kernel::HLERequestContext& ctx); void SendToSingle(Kernel::HLERequestContext& ctx);
void RecvFromOther(Kernel::HLERequestContext& ctx); void RecvFromOther(Kernel::HLERequestContext& ctx);
void RecvFrom(Kernel::HLERequestContext& ctx); void RecvFrom(Kernel::HLERequestContext& ctx);
void Poll(Kernel::HLERequestContext& ctx); void Poll(Kernel::HLERequestContext& ctx);
void GetSockName(Kernel::HLERequestContext& ctx); void GetSockName(Kernel::HLERequestContext& ctx);
void Shutdown(Kernel::HLERequestContext& ctx); void Shutdown(Kernel::HLERequestContext& ctx);
void GetHostByAddr(Kernel::HLERequestContext& ctx);
void GetHostByName(Kernel::HLERequestContext& ctx); void GetHostByName(Kernel::HLERequestContext& ctx);
void GetPeerName(Kernel::HLERequestContext& ctx); void GetPeerName(Kernel::HLERequestContext& ctx);
void Connect(Kernel::HLERequestContext& ctx); void Connect(Kernel::HLERequestContext& ctx);
@ -121,6 +139,9 @@ private:
void GetSockOpt(Kernel::HLERequestContext& ctx); void GetSockOpt(Kernel::HLERequestContext& ctx);
void SetSockOpt(Kernel::HLERequestContext& ctx); void SetSockOpt(Kernel::HLERequestContext& ctx);
void GetNetworkOpt(Kernel::HLERequestContext& ctx); void GetNetworkOpt(Kernel::HLERequestContext& ctx);
void SendToMultiple(Kernel::HLERequestContext& ctx);
void CloseSockets(Kernel::HLERequestContext& ctx);
void AddGlobalSocket(Kernel::HLERequestContext& ctx);
// Some platforms seem to have GetAddrInfo and GetNameInfo defined as macros, // Some platforms seem to have GetAddrInfo and GetNameInfo defined as macros,
// so we have to use a different name here. // so we have to use a different name here.
@ -133,17 +154,10 @@ private:
return next_socket_id++; return next_socket_id++;
} }
// System timer adjust
std::chrono::time_point<std::chrono::steady_clock> adjust_value_last;
void PreTimerAdjust();
void PostTimerAdjust(Kernel::HLERequestContext& ctx, const std::string& caller_method);
/// Close all open sockets
void CleanupSockets();
/// Holds info about the currently open sockets /// Holds info about the currently open sockets
friend struct CTRPollFD; friend struct CTRPollFD;
std::unordered_map<u32, SocketHolder> open_sockets; std::unordered_map<u32, SocketHolder> created_sockets;
std::set<u32> initialized_processes;
/// Cache interface info for the current session /// Cache interface info for the current session
/// These two fields are not saved to savestates on purpose /// These two fields are not saved to savestates on purpose
@ -155,7 +169,8 @@ private:
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int) {
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this); ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
ar& open_sockets; ar& created_sockets;
ar& initialized_processes;
} }
friend class boost::serialization::access; friend class boost::serialization::access;
}; };