mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue