Implement/Fix more SOC related functions (#6267)
* Implement SOC_U::GetHostByName and partial SOC_U::GetNetworkOpt * Implement AC::GetWifiStatus, and get proper network interface. * Minor fixes * More minor fixes * Even more fixes * Fix Get/Set SockOpt * Implement SendToOther * Apply suggestions and fix timer advance * Fix variable name * Add more sockopt values and fix send/recv flags. * Fix dontwait logic * Add missing header for linux * Remove TCP_STDURG * Fix poll and add more 3ds <-> platform conversions * Finish implementing all platform <-> 3ds conversion. * Disable UDP connreset and fix poll again. * Fix compile issues * Apply suggestions * Fix compiler issues * Fix compiler errors (again) * Fix GetAddrInfo * Use IPC::MakeHeader instead of raw hardcoded value.
This commit is contained in:
parent
fa8c530e10
commit
5c45c97ff9
6 changed files with 983 additions and 234 deletions
|
@ -173,22 +173,6 @@ void Timing::Timer::MoveEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Timing::Timer::StartAdjust() {
|
|
||||||
ASSERT((adjust_value_curr_handle & 1) == 0); // Should always be even
|
|
||||||
adjust_value_last = std::chrono::steady_clock::now();
|
|
||||||
return ++adjust_value_curr_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timing::Timer::EndAdjust(u32 start_adjust_handle) {
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> new_timer = std::chrono::steady_clock::now();
|
|
||||||
ASSERT(new_timer >= adjust_value_last && start_adjust_handle == adjust_value_curr_handle);
|
|
||||||
AddTicks(nsToCycles(static_cast<float>(
|
|
||||||
std::chrono::duration_cast<std::chrono::nanoseconds>(new_timer - adjust_value_last)
|
|
||||||
.count() /
|
|
||||||
cpu_clock_scale)));
|
|
||||||
++adjust_value_curr_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 Timing::Timer::GetMaxSliceLength() const {
|
s64 Timing::Timer::GetMaxSliceLength() const {
|
||||||
const auto& next_event = event_queue.begin();
|
const auto& next_event = event_queue.begin();
|
||||||
if (next_event != event_queue.end()) {
|
if (next_event != event_queue.end()) {
|
||||||
|
|
|
@ -203,11 +203,6 @@ public:
|
||||||
|
|
||||||
void MoveEvents();
|
void MoveEvents();
|
||||||
|
|
||||||
// Use these two functions to adjust the guest system tick on host blocking operations, so
|
|
||||||
// that the guest can tell how much time passed during the host call.
|
|
||||||
u32 StartAdjust();
|
|
||||||
void EndAdjust(u32 start_adjust_handle);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Timing;
|
friend class Timing;
|
||||||
// The queue is a min-heap using std::make_heap/push_heap/pop_heap.
|
// The queue is a min-heap using std::make_heap/push_heap/pop_heap.
|
||||||
|
@ -233,8 +228,6 @@ public:
|
||||||
s64 executed_ticks = 0;
|
s64 executed_ticks = 0;
|
||||||
u64 idled_cycles = 0;
|
u64 idled_cycles = 0;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> adjust_value_last;
|
|
||||||
u32 adjust_value_curr_handle = 0;
|
|
||||||
// Stores a scaling for the internal clockspeed. Changing this number results in
|
// Stores a scaling for the internal clockspeed. Changing this number results in
|
||||||
// under/overclocking the guest cpu
|
// under/overclocking the guest cpu
|
||||||
double cpu_clock_scale = 1.0;
|
double cpu_clock_scale = 1.0;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
#include "core/hle/service/ac/ac.h"
|
#include "core/hle/service/ac/ac.h"
|
||||||
#include "core/hle/service/ac/ac_i.h"
|
#include "core/hle/service/ac/ac_i.h"
|
||||||
#include "core/hle/service/ac/ac_u.h"
|
#include "core/hle/service/ac/ac_u.h"
|
||||||
|
#include "core/hle/service/soc_u.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace Service::AC {
|
namespace Service::AC {
|
||||||
|
@ -91,15 +93,19 @@ void Module::Interface::GetCloseResult(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx, 0xD, 0, 0);
|
IPC::RequestParser rp(ctx, 0xD, 0, 0);
|
||||||
|
bool can_reach_internet = false;
|
||||||
|
|
||||||
// TODO(purpasmart96): This function is only a stub,
|
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(Core::System::GetInstance());
|
||||||
// it returns a valid result without implementing full functionality.
|
if (socu_module) {
|
||||||
|
can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value();
|
||||||
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.Push<u32>(0); // Connection type set to none
|
rb.Push<u32>(static_cast<u32>(can_reach_internet ? (Settings::values.is_new_3ds
|
||||||
|
? WifiStatus::STATUS_CONNECTED_N3DS
|
||||||
LOG_WARNING(Service_AC, "(STUBBED) called");
|
: WifiStatus::STATUS_CONNECTED_O3DS)
|
||||||
|
: WifiStatus::STATUS_DISCONNECTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
|
@ -142,6 +142,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
enum class WifiStatus {
|
||||||
|
STATUS_DISCONNECTED = 0,
|
||||||
|
STATUS_CONNECTED_O3DS = 1,
|
||||||
|
STATUS_CONNECTED_N3DS = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct ACConfig {
|
struct ACConfig {
|
||||||
std::array<u8, 0x200> data;
|
std::array<u8, 0x200> data;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
#include <boost/serialization/unordered_map.hpp>
|
#include <boost/serialization/unordered_map.hpp>
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
@ -21,10 +22,10 @@ struct SocketHolder {
|
||||||
using SOCKET = unsigned long long;
|
using SOCKET = unsigned long long;
|
||||||
SOCKET socket_fd; ///< The socket descriptor
|
SOCKET socket_fd; ///< The socket descriptor
|
||||||
#else
|
#else
|
||||||
u32 socket_fd; ///< The socket descriptor
|
int socket_fd; ///< The socket descriptor
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
bool blocking; ///< Whether the socket is blocking or not, it is only read on Windows.
|
bool blocking = true; ///< Whether the socket is blocking or not.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -40,10 +41,59 @@ public:
|
||||||
SOC_U();
|
SOC_U();
|
||||||
~SOC_U();
|
~SOC_U();
|
||||||
|
|
||||||
|
struct InterfaceInfo {
|
||||||
|
u32 address;
|
||||||
|
u32 netmask;
|
||||||
|
u32 broadcast;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets the interface info that is able to reach the internet.
|
||||||
|
std::optional<InterfaceInfo> GetDefaultInterfaceInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr ResultCode ERR_INVALID_HANDLE =
|
static constexpr ResultCode ERR_INVALID_HANDLE =
|
||||||
ResultCode(ErrorDescription::InvalidHandle, ErrorModule::SOC, ErrorSummary::InvalidArgument,
|
ResultCode(ErrorDescription::InvalidHandle, ErrorModule::SOC, ErrorSummary::InvalidArgument,
|
||||||
ErrorLevel::Permanent);
|
ErrorLevel::Permanent);
|
||||||
|
static constexpr u32 SOC_ERR_INAVLID_ENUM_VALUE = 0xFFFF8025;
|
||||||
|
|
||||||
|
static constexpr u32 SOC_SOL_IP = 0x0000;
|
||||||
|
static constexpr u32 SOC_SOL_TCP = 0x0006;
|
||||||
|
static constexpr u32 SOC_SOL_CONFIG = 0xFFFE;
|
||||||
|
static constexpr u32 SOC_SOL_SOCKET = 0xFFFF;
|
||||||
|
|
||||||
|
static const std::unordered_map<u64, std::pair<int, int>> sockopt_map;
|
||||||
|
static std::pair<int, int> TranslateSockOpt(int level, int opt);
|
||||||
|
bool GetSocketBlocking(const SocketHolder& socket_holder);
|
||||||
|
u32 SetSocketBlocking(SocketHolder& socket_holder, bool blocking);
|
||||||
|
|
||||||
|
// From
|
||||||
|
// https://github.com/devkitPro/libctru/blob/1de86ea38aec419744149daf692556e187d4678a/libctru/include/3ds/services/soc.h#L15
|
||||||
|
enum class NetworkOpt {
|
||||||
|
NETOPT_MAC_ADDRESS = 0x1004, ///< The mac address of the interface
|
||||||
|
NETOPT_ARP_TABLE = 0x3002, ///< The ARP table
|
||||||
|
NETOPT_IP_INFO = 0x4003, ///< The current IP setup
|
||||||
|
NETOPT_IP_MTU = 0x4004, ///< The value of the IP MTU
|
||||||
|
NETOPT_ROUTING_TABLE = 0x4006, ///< The routing table
|
||||||
|
NETOPT_UDP_NUMBER = 0x8002, ///< The number of sockets in the UDP table
|
||||||
|
NETOPT_UDP_TABLE = 0x8003, ///< The table of opened UDP sockets
|
||||||
|
NETOPT_TCP_NUMBER = 0x9002, ///< The number of sockets in the TCP table
|
||||||
|
NETOPT_TCP_TABLE = 0x9003, ///< The table of opened TCP sockets
|
||||||
|
NETOPT_DNS_TABLE = 0xB003, ///< The table of the DNS servers
|
||||||
|
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);
|
||||||
|
@ -52,18 +102,21 @@ private:
|
||||||
void Accept(Kernel::HLERequestContext& ctx);
|
void Accept(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 SendTo(Kernel::HLERequestContext& ctx);
|
void SendTo(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 GetHostByName(Kernel::HLERequestContext& ctx);
|
||||||
void GetPeerName(Kernel::HLERequestContext& ctx);
|
void GetPeerName(Kernel::HLERequestContext& ctx);
|
||||||
void Connect(Kernel::HLERequestContext& ctx);
|
void Connect(Kernel::HLERequestContext& ctx);
|
||||||
void InitializeSockets(Kernel::HLERequestContext& ctx);
|
void InitializeSockets(Kernel::HLERequestContext& ctx);
|
||||||
void ShutdownSockets(Kernel::HLERequestContext& ctx);
|
void ShutdownSockets(Kernel::HLERequestContext& ctx);
|
||||||
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);
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -77,9 +130,9 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// System timer adjust
|
// System timer adjust
|
||||||
u32 timer_adjust_handle;
|
std::chrono::time_point<std::chrono::steady_clock> adjust_value_last;
|
||||||
void PreTimerAdjust();
|
void PreTimerAdjust();
|
||||||
void PostTimerAdjust();
|
void PostTimerAdjust(Kernel::HLERequestContext& ctx, const std::string& caller_method);
|
||||||
|
|
||||||
/// Close all open sockets
|
/// Close all open sockets
|
||||||
void CleanupSockets();
|
void CleanupSockets();
|
||||||
|
@ -88,15 +141,23 @@ private:
|
||||||
friend struct CTRPollFD;
|
friend struct CTRPollFD;
|
||||||
std::unordered_map<u32, SocketHolder> open_sockets;
|
std::unordered_map<u32, SocketHolder> open_sockets;
|
||||||
|
|
||||||
|
/// Cache interface info for the current session
|
||||||
|
/// These two fields are not saved to savestates on purpose
|
||||||
|
/// as network interfaces may change and it's better to.
|
||||||
|
/// obtain them again between play sessions.
|
||||||
|
bool interface_info_cached = false;
|
||||||
|
InterfaceInfo interface_info;
|
||||||
|
|
||||||
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& open_sockets;
|
||||||
ar& timer_adjust_handle;
|
|
||||||
}
|
}
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<SOC_U> GetService(Core::System& system);
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::SOC
|
} // namespace Service::SOC
|
||||||
|
|
Loading…
Reference in a new issue