mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40: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 { | ||||
|     const auto& next_event = event_queue.begin(); | ||||
|     if (next_event != event_queue.end()) { | ||||
|  |  | |||
|  | @ -203,11 +203,6 @@ public: | |||
| 
 | ||||
|         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: | ||||
|         friend class Timing; | ||||
|         // The queue is a min-heap using std::make_heap/push_heap/pop_heap.
 | ||||
|  | @ -233,8 +228,6 @@ public: | |||
|         s64 executed_ticks = 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
 | ||||
|         // under/overclocking the guest cpu
 | ||||
|         double cpu_clock_scale = 1.0; | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "common/archives.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/ipc_helpers.h" | ||||
|  | @ -15,6 +16,7 @@ | |||
| #include "core/hle/service/ac/ac.h" | ||||
| #include "core/hle/service/ac/ac_i.h" | ||||
| #include "core/hle/service/ac/ac_u.h" | ||||
| #include "core/hle/service/soc_u.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| namespace Service::AC { | ||||
|  | @ -91,15 +93,19 @@ void Module::Interface::GetCloseResult(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
| void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp(ctx, 0xD, 0, 0); | ||||
|     bool can_reach_internet = false; | ||||
| 
 | ||||
|     // TODO(purpasmart96): This function is only a stub,
 | ||||
|     // it returns a valid result without implementing full functionality.
 | ||||
|     std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(Core::System::GetInstance()); | ||||
|     if (socu_module) { | ||||
|         can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value(); | ||||
|     } | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push<u32>(0); // Connection type set to none
 | ||||
| 
 | ||||
|     LOG_WARNING(Service_AC, "(STUBBED) called"); | ||||
|     rb.Push<u32>(static_cast<u32>(can_reach_internet ? (Settings::values.is_new_3ds | ||||
|                                                             ? WifiStatus::STATUS_CONNECTED_N3DS | ||||
|                                                             : WifiStatus::STATUS_CONNECTED_O3DS) | ||||
|                                                      : WifiStatus::STATUS_DISCONNECTED)); | ||||
| } | ||||
| 
 | ||||
| void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) { | ||||
|  |  | |||
|  | @ -142,6 +142,12 @@ public: | |||
|     }; | ||||
| 
 | ||||
| protected: | ||||
|     enum class WifiStatus { | ||||
|         STATUS_DISCONNECTED = 0, | ||||
|         STATUS_CONNECTED_O3DS = 1, | ||||
|         STATUS_CONNECTED_N3DS = 2, | ||||
|     }; | ||||
| 
 | ||||
|     struct ACConfig { | ||||
|         std::array<u8, 0x200> data; | ||||
|     }; | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -5,6 +5,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <unordered_map> | ||||
| #include <utility> | ||||
| #include <boost/serialization/unordered_map.hpp> | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | @ -21,10 +22,10 @@ struct SocketHolder { | |||
|     using SOCKET = unsigned long long; | ||||
|     SOCKET socket_fd; ///< The socket descriptor
 | ||||
| #else | ||||
|     u32 socket_fd; ///< The socket descriptor
 | ||||
|     int socket_fd; ///< The socket descriptor
 | ||||
| #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: | ||||
|     template <class Archive> | ||||
|  | @ -40,10 +41,59 @@ public: | |||
|     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: | ||||
|     static constexpr ResultCode ERR_INVALID_HANDLE = | ||||
|         ResultCode(ErrorDescription::InvalidHandle, ErrorModule::SOC, ErrorSummary::InvalidArgument, | ||||
|                    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 Bind(Kernel::HLERequestContext& ctx); | ||||
|  | @ -52,18 +102,21 @@ private: | |||
|     void Accept(Kernel::HLERequestContext& ctx); | ||||
|     void GetHostId(Kernel::HLERequestContext& ctx); | ||||
|     void Close(Kernel::HLERequestContext& ctx); | ||||
|     void SendToOther(Kernel::HLERequestContext& ctx); | ||||
|     void SendTo(Kernel::HLERequestContext& ctx); | ||||
|     void RecvFromOther(Kernel::HLERequestContext& ctx); | ||||
|     void RecvFrom(Kernel::HLERequestContext& ctx); | ||||
|     void Poll(Kernel::HLERequestContext& ctx); | ||||
|     void GetSockName(Kernel::HLERequestContext& ctx); | ||||
|     void Shutdown(Kernel::HLERequestContext& ctx); | ||||
|     void GetHostByName(Kernel::HLERequestContext& ctx); | ||||
|     void GetPeerName(Kernel::HLERequestContext& ctx); | ||||
|     void Connect(Kernel::HLERequestContext& ctx); | ||||
|     void InitializeSockets(Kernel::HLERequestContext& ctx); | ||||
|     void ShutdownSockets(Kernel::HLERequestContext& ctx); | ||||
|     void GetSockOpt(Kernel::HLERequestContext& ctx); | ||||
|     void SetSockOpt(Kernel::HLERequestContext& ctx); | ||||
|     void GetNetworkOpt(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
|     // Some platforms seem to have GetAddrInfo and GetNameInfo defined as macros,
 | ||||
|     // so we have to use a different name here.
 | ||||
|  | @ -77,9 +130,9 @@ private: | |||
|     } | ||||
| 
 | ||||
|     // System timer adjust
 | ||||
|     u32 timer_adjust_handle; | ||||
|     std::chrono::time_point<std::chrono::steady_clock> adjust_value_last; | ||||
|     void PreTimerAdjust(); | ||||
|     void PostTimerAdjust(); | ||||
|     void PostTimerAdjust(Kernel::HLERequestContext& ctx, const std::string& caller_method); | ||||
| 
 | ||||
|     /// Close all open sockets
 | ||||
|     void CleanupSockets(); | ||||
|  | @ -88,15 +141,23 @@ private: | |||
|     friend struct CTRPollFD; | ||||
|     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> | ||||
|     void serialize(Archive& ar, const unsigned int) { | ||||
|         ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this); | ||||
|         ar& open_sockets; | ||||
|         ar& timer_adjust_handle; | ||||
|     } | ||||
|     friend class boost::serialization::access; | ||||
| }; | ||||
| 
 | ||||
| std::shared_ptr<SOC_U> GetService(Core::System& system); | ||||
| 
 | ||||
| void InstallInterfaces(Core::System& system); | ||||
| 
 | ||||
| } // namespace Service::SOC
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue