IGeneralService.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using Ryujinx.Common;
  2. using Ryujinx.Common.Logging;
  3. using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
  4. using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
  5. using System;
  6. using System.Net.NetworkInformation;
  7. namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
  8. {
  9. class IGeneralService : IpcService, IDisposable
  10. {
  11. private GeneralServiceDetail _generalServiceDetail;
  12. public IGeneralService()
  13. {
  14. _generalServiceDetail = new GeneralServiceDetail
  15. {
  16. ClientId = GeneralServiceManager.Count,
  17. IsAnyInternetRequestAccepted = true // NOTE: Why not accept any internet request?
  18. };
  19. GeneralServiceManager.Add(_generalServiceDetail);
  20. }
  21. [Command(1)]
  22. // GetClientId() -> buffer<nn::nifm::ClientId, 0x1a, 4>
  23. public ResultCode GetClientId(ServiceCtx context)
  24. {
  25. long position = context.Request.RecvListBuff[0].Position;
  26. context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(4);
  27. context.Memory.Write((ulong)position, _generalServiceDetail.ClientId);
  28. return ResultCode.Success;
  29. }
  30. [Command(4)]
  31. // CreateRequest(u32 version) -> object<nn::nifm::detail::IRequest>
  32. public ResultCode CreateRequest(ServiceCtx context)
  33. {
  34. uint version = context.RequestData.ReadUInt32();
  35. MakeObject(context, new IRequest(context.Device.System, version));
  36. // Doesn't occur in our case.
  37. // return ResultCode.ObjectIsNull;
  38. Logger.Stub?.PrintStub(LogClass.ServiceNifm, new { version });
  39. return ResultCode.Success;
  40. }
  41. [Command(12)]
  42. // GetCurrentIpAddress() -> nn::nifm::IpV4Address
  43. public ResultCode GetCurrentIpAddress(ServiceCtx context)
  44. {
  45. (_, UnicastIPAddressInformation unicastAddress) = GetLocalInterface();
  46. if (unicastAddress == null)
  47. {
  48. return ResultCode.NoInternetConnection;
  49. }
  50. context.ResponseData.WriteStruct(new IpV4Address(unicastAddress.Address));
  51. Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
  52. return ResultCode.Success;
  53. }
  54. [Command(15)]
  55. // GetCurrentIpConfigInfo() -> (nn::nifm::IpAddressSetting, nn::nifm::DnsSetting)
  56. public ResultCode GetCurrentIpConfigInfo(ServiceCtx context)
  57. {
  58. (IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface();
  59. if (interfaceProperties == null)
  60. {
  61. return ResultCode.NoInternetConnection;
  62. }
  63. Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
  64. context.ResponseData.WriteStruct(new IpAddressSetting(interfaceProperties, unicastAddress));
  65. context.ResponseData.WriteStruct(new DnsSetting(interfaceProperties));
  66. return ResultCode.Success;
  67. }
  68. [Command(18)]
  69. // GetInternetConnectionStatus() -> nn::nifm::detail::sf::InternetConnectionStatus
  70. public ResultCode GetInternetConnectionStatus(ServiceCtx context)
  71. {
  72. if (!NetworkInterface.GetIsNetworkAvailable())
  73. {
  74. return ResultCode.NoInternetConnection;
  75. }
  76. InternetConnectionStatus internetConnectionStatus = new InternetConnectionStatus
  77. {
  78. Type = InternetConnectionType.WiFi,
  79. WifiStrength = 3,
  80. State = InternetConnectionState.Connected,
  81. };
  82. context.ResponseData.WriteStruct(internetConnectionStatus);
  83. return ResultCode.Success;
  84. }
  85. [Command(21)]
  86. // IsAnyInternetRequestAccepted(buffer<nn::nifm::ClientId, 0x19, 4>) -> bool
  87. public ResultCode IsAnyInternetRequestAccepted(ServiceCtx context)
  88. {
  89. long position = context.Request.PtrBuff[0].Position;
  90. long size = context.Request.PtrBuff[0].Size;
  91. int clientId = context.Memory.Read<int>((ulong)position);
  92. context.ResponseData.Write(GeneralServiceManager.Get(clientId).IsAnyInternetRequestAccepted);
  93. return ResultCode.Success;
  94. }
  95. private (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface()
  96. {
  97. if (!NetworkInterface.GetIsNetworkAvailable())
  98. {
  99. return (null, null);
  100. }
  101. IPInterfaceProperties targetProperties = null;
  102. UnicastIPAddressInformation targetAddressInfo = null;
  103. NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
  104. foreach (NetworkInterface adapter in interfaces)
  105. {
  106. // Ignore loopback and non IPv4 capable interface.
  107. if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && adapter.Supports(NetworkInterfaceComponent.IPv4))
  108. {
  109. IPInterfaceProperties properties = adapter.GetIPProperties();
  110. if (properties.GatewayAddresses.Count > 0 && properties.DnsAddresses.Count > 1)
  111. {
  112. foreach (UnicastIPAddressInformation info in properties.UnicastAddresses)
  113. {
  114. // Only accept an IPv4 address
  115. if (info.Address.GetAddressBytes().Length == 4)
  116. {
  117. targetProperties = properties;
  118. targetAddressInfo = info;
  119. break;
  120. }
  121. }
  122. }
  123. // Found the target interface, stop here.
  124. if (targetProperties != null)
  125. {
  126. break;
  127. }
  128. }
  129. }
  130. return (targetProperties, targetAddressInfo);
  131. }
  132. public void Dispose()
  133. {
  134. GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
  135. }
  136. }
  137. }