IManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Cpu;
  3. using Ryujinx.HLE.Exceptions;
  4. using Ryujinx.HLE.HOS.Services.Settings;
  5. using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager;
  6. using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Types;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
  10. {
  11. [Service("nsd:a")] // Max sessions: 5
  12. [Service("nsd:u")] // Max sessions: 20
  13. class IManager : IpcService
  14. {
  15. public static readonly NsdSettings NsdSettings;
  16. private readonly FqdnResolver _fqdnResolver;
  17. private bool _isInitialized = false;
  18. public IManager(ServiceCtx context)
  19. {
  20. _fqdnResolver = new FqdnResolver();
  21. _isInitialized = true;
  22. }
  23. static IManager()
  24. {
  25. // TODO: Load nsd settings through the savedata 0x80000000000000B0 (nsdsave:/).
  26. if (!NxSettings.Settings.TryGetValue("nsd!test_mode", out object testMode))
  27. {
  28. // return ResultCode.InvalidSettingsValue;
  29. }
  30. if (!NxSettings.Settings.TryGetValue("nsd!environment_identifier", out object environmentIdentifier))
  31. {
  32. // return ResultCode.InvalidSettingsValue;
  33. }
  34. NsdSettings = new NsdSettings
  35. {
  36. Initialized = true,
  37. TestMode = (bool)testMode,
  38. Environment = (string)environmentIdentifier
  39. };
  40. }
  41. [CommandHipc(5)] // 11.0.0+
  42. // GetSettingUrl() -> buffer<unknown<0x100>, 0x16>
  43. public ResultCode GetSettingUrl(ServiceCtx context)
  44. {
  45. throw new ServiceNotImplementedException(this, context);
  46. }
  47. [CommandHipc(10)]
  48. // GetSettingName() -> buffer<unknown<0x100>, 0x16>
  49. public ResultCode GetSettingName(ServiceCtx context)
  50. {
  51. throw new ServiceNotImplementedException(this, context);
  52. }
  53. [CommandHipc(11)]
  54. // GetEnvironmentIdentifier() -> buffer<bytes<8> environment_identifier, 0x16>
  55. public ResultCode GetEnvironmentIdentifier(ServiceCtx context)
  56. {
  57. (ulong outputPosition, ulong outputSize) = context.Request.GetBufferType0x22();
  58. MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
  59. ResultCode result = _fqdnResolver.GetEnvironmentIdentifier(out string identifier);
  60. if (result == ResultCode.Success)
  61. {
  62. byte[] identifierBuffer = Encoding.UTF8.GetBytes(identifier);
  63. context.Memory.Write(outputPosition, identifierBuffer);
  64. }
  65. return result;
  66. }
  67. [CommandHipc(12)]
  68. // GetDeviceId() -> bytes<0x10, 1>
  69. public ResultCode GetDeviceId(ServiceCtx context)
  70. {
  71. // NOTE: Stubbed in system module.
  72. return ResultCode.Success;
  73. }
  74. [CommandHipc(13)]
  75. // DeleteSettings(u32)
  76. public ResultCode DeleteSettings(ServiceCtx context)
  77. {
  78. uint unknown = context.RequestData.ReadUInt32();
  79. if (!_isInitialized)
  80. {
  81. return ResultCode.ServiceNotInitialized;
  82. }
  83. if (unknown > 1)
  84. {
  85. return ResultCode.InvalidArgument;
  86. }
  87. if (unknown == 1)
  88. {
  89. NxSettings.Settings.TryGetValue("nsd!environment_identifier", out object environmentIdentifier);
  90. if ((string)environmentIdentifier == NsdSettings.Environment)
  91. {
  92. // TODO: Call nn::fs::DeleteSystemFile() to delete the savedata file and return ResultCode.
  93. }
  94. else
  95. {
  96. // TODO: Mount the savedata file and return ResultCode.
  97. }
  98. }
  99. else
  100. {
  101. // TODO: Call nn::fs::DeleteSystemFile() to delete the savedata file and return ResultCode.
  102. }
  103. return ResultCode.Success;
  104. }
  105. [CommandHipc(14)]
  106. // ImportSettings(u32, buffer<unknown, 5>) -> buffer<unknown, 6>
  107. public ResultCode ImportSettings(ServiceCtx context)
  108. {
  109. throw new ServiceNotImplementedException(this, context);
  110. }
  111. [CommandHipc(15)] // 4.0.0+
  112. // SetChangeEnvironmentIdentifierDisabled(bytes<1>)
  113. public ResultCode SetChangeEnvironmentIdentifierDisabled(ServiceCtx context)
  114. {
  115. byte disabled = context.RequestData.ReadByte();
  116. // TODO: When sys:set service calls will be implemented
  117. /*
  118. if (((nn::settings::detail::GetServiceDiscoveryControlSettings() ^ disabled) & 1) != 0 )
  119. {
  120. nn::settings::detail::SetServiceDiscoveryControlSettings(disabled & 1);
  121. }
  122. */
  123. Logger.Stub?.PrintStub(LogClass.ServiceNsd, new { disabled });
  124. return ResultCode.Success;
  125. }
  126. [CommandHipc(20)]
  127. // Resolve(buffer<unknown<0x100>, 0x15>) -> buffer<unknown<0x100>, 0x16>
  128. public ResultCode Resolve(ServiceCtx context)
  129. {
  130. ulong outputPosition = context.Request.ReceiveBuff[0].Position;
  131. ulong outputSize = context.Request.ReceiveBuff[0].Size;
  132. ResultCode result = _fqdnResolver.ResolveEx(context, out _, out string resolvedAddress);
  133. if ((ulong)resolvedAddress.Length > outputSize)
  134. {
  135. return ResultCode.InvalidArgument;
  136. }
  137. byte[] resolvedAddressBuffer = Encoding.UTF8.GetBytes(resolvedAddress);
  138. MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
  139. context.Memory.Write(outputPosition, resolvedAddressBuffer);
  140. return result;
  141. }
  142. [CommandHipc(21)]
  143. // ResolveEx(buffer<unknown<0x100>, 0x15>) -> (u32, buffer<unknown<0x100>, 0x16>)
  144. public ResultCode ResolveEx(ServiceCtx context)
  145. {
  146. ulong outputPosition = context.Request.ReceiveBuff[0].Position;
  147. ulong outputSize = context.Request.ReceiveBuff[0].Size;
  148. ResultCode result = _fqdnResolver.ResolveEx(context, out ResultCode errorCode, out string resolvedAddress);
  149. if ((ulong)resolvedAddress.Length > outputSize)
  150. {
  151. return ResultCode.InvalidArgument;
  152. }
  153. byte[] resolvedAddressBuffer = Encoding.UTF8.GetBytes(resolvedAddress);
  154. MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
  155. context.Memory.Write(outputPosition, resolvedAddressBuffer);
  156. context.ResponseData.Write((int)errorCode);
  157. return result;
  158. }
  159. [CommandHipc(30)]
  160. // GetNasServiceSetting(buffer<unknown<0x10>, 0x15>) -> buffer<unknown<0x108>, 0x16>
  161. public ResultCode GetNasServiceSetting(ServiceCtx context)
  162. {
  163. throw new ServiceNotImplementedException(this, context);
  164. }
  165. [CommandHipc(31)]
  166. // GetNasServiceSettingEx(buffer<unknown<0x10>, 0x15>) -> (u32, buffer<unknown<0x108>, 0x16>)
  167. public ResultCode GetNasServiceSettingEx(ServiceCtx context)
  168. {
  169. throw new ServiceNotImplementedException(this, context);
  170. }
  171. [CommandHipc(40)]
  172. // GetNasRequestFqdn() -> buffer<unknown<0x100>, 0x16>
  173. public ResultCode GetNasRequestFqdn(ServiceCtx context)
  174. {
  175. throw new ServiceNotImplementedException(this, context);
  176. }
  177. [CommandHipc(41)]
  178. // GetNasRequestFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
  179. public ResultCode GetNasRequestFqdnEx(ServiceCtx context)
  180. {
  181. throw new ServiceNotImplementedException(this, context);
  182. }
  183. [CommandHipc(42)]
  184. // GetNasApiFqdn() -> buffer<unknown<0x100>, 0x16>
  185. public ResultCode GetNasApiFqdn(ServiceCtx context)
  186. {
  187. throw new ServiceNotImplementedException(this, context);
  188. }
  189. [CommandHipc(43)]
  190. // GetNasApiFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
  191. public ResultCode GetNasApiFqdnEx(ServiceCtx context)
  192. {
  193. throw new ServiceNotImplementedException(this, context);
  194. }
  195. [CommandHipc(50)]
  196. // GetCurrentSetting() -> buffer<unknown<0x12bf0>, 0x16>
  197. public ResultCode GetCurrentSetting(ServiceCtx context)
  198. {
  199. throw new ServiceNotImplementedException(this, context);
  200. }
  201. [CommandHipc(51)] // 9.0.0+
  202. // WriteTestParameter(buffer<?>)
  203. public ResultCode WriteTestParameter(ServiceCtx context)
  204. {
  205. // TODO: Write test parameter through the savedata 0x80000000000000B0 (nsdsave:/test_parameter).
  206. throw new ServiceNotImplementedException(this, context);
  207. }
  208. [CommandHipc(52)] // 9.0.0+
  209. // ReadTestParameter() -> buffer<?>
  210. public ResultCode ReadTestParameter(ServiceCtx context)
  211. {
  212. // TODO: Read test parameter through the savedata 0x80000000000000B0 (nsdsave:/test_parameter).
  213. throw new ServiceNotImplementedException(this, context);
  214. }
  215. [CommandHipc(60)]
  216. // ReadSaveDataFromFsForTest() -> buffer<unknown<0x12bf0>, 0x16>
  217. public ResultCode ReadSaveDataFromFsForTest(ServiceCtx context)
  218. {
  219. if (!_isInitialized)
  220. {
  221. return ResultCode.ServiceNotInitialized;
  222. }
  223. // TODO: Read the savedata 0x80000000000000B0 (nsdsave:/file) and write it inside the buffer.
  224. Logger.Stub?.PrintStub(LogClass.ServiceNsd);
  225. return ResultCode.Success;
  226. }
  227. [CommandHipc(61)]
  228. // WriteSaveDataToFsForTest(buffer<unknown<0x12bf0>, 0x15>)
  229. public ResultCode WriteSaveDataToFsForTest(ServiceCtx context)
  230. {
  231. if (!_isInitialized)
  232. {
  233. return ResultCode.ServiceNotInitialized;
  234. }
  235. // TODO: When sys:set service calls will be implemented
  236. /*
  237. if (nn::settings::detail::GetSettingsItemValueSize("nsd", "test_mode") != 1)
  238. {
  239. return ResultCode.InvalidSettingsValue;
  240. }
  241. */
  242. if (!NsdSettings.TestMode)
  243. {
  244. return ResultCode.InvalidSettingsValue;
  245. }
  246. // TODO: Write the buffer inside the savedata 0x80000000000000B0 (nsdsave:/file).
  247. Logger.Stub?.PrintStub(LogClass.ServiceNsd);
  248. return ResultCode.Success;
  249. }
  250. [CommandHipc(62)]
  251. // DeleteSaveDataOfFsForTest()
  252. public ResultCode DeleteSaveDataOfFsForTest(ServiceCtx context)
  253. {
  254. if (!_isInitialized)
  255. {
  256. return ResultCode.ServiceNotInitialized;
  257. }
  258. // TODO: When sys:set service calls will be implemented
  259. /*
  260. if (nn::settings::detail::GetSettingsItemValueSize("nsd", "test_mode") != 1)
  261. {
  262. return ResultCode.InvalidSettingsValue;
  263. }
  264. */
  265. if (!NsdSettings.TestMode)
  266. {
  267. return ResultCode.InvalidSettingsValue;
  268. }
  269. // TODO: Delete the savedata 0x80000000000000B0.
  270. Logger.Stub?.PrintStub(LogClass.ServiceNsd);
  271. return ResultCode.Success;
  272. }
  273. [CommandHipc(63)] // 4.0.0+
  274. // IsChangeEnvironmentIdentifierDisabled() -> bytes<1>
  275. public ResultCode IsChangeEnvironmentIdentifierDisabled(ServiceCtx context)
  276. {
  277. // TODO: When sys:set service calls will be implemented use nn::settings::detail::GetServiceDiscoveryControlSettings()
  278. bool disabled = false;
  279. context.ResponseData.Write(disabled);
  280. Logger.Stub?.PrintStub(LogClass.ServiceNsd, new { disabled });
  281. return ResultCode.Success;
  282. }
  283. [CommandHipc(100)] // 10.0.0+
  284. // GetApplicationServerEnvironmentType() -> bytes<1>
  285. public ResultCode GetApplicationServerEnvironmentType(ServiceCtx context)
  286. {
  287. // TODO: Mount the savedata 0x80000000000000B0 (nsdsave:/test_parameter) and returns the environment type stored inside if the mount succeed.
  288. // Returns ResultCode.NullOutputObject if failed.
  289. ResultCode result = _fqdnResolver.GetEnvironmentIdentifier(out string identifier);
  290. if (result != ResultCode.Success)
  291. {
  292. return result;
  293. }
  294. byte environmentType = identifier.Substring(0, 2) switch
  295. {
  296. "lp" => (byte)ApplicationServerEnvironmentType.Lp,
  297. "sd" => (byte)ApplicationServerEnvironmentType.Sd,
  298. "sp" => (byte)ApplicationServerEnvironmentType.Sp,
  299. "dp" => (byte)ApplicationServerEnvironmentType.Dp,
  300. _ => (byte)ApplicationServerEnvironmentType.None
  301. };
  302. context.ResponseData.Write(environmentType);
  303. return ResultCode.Success;
  304. }
  305. [CommandHipc(101)] // 10.0.0+
  306. // SetApplicationServerEnvironmentType(bytes<1>)
  307. public ResultCode SetApplicationServerEnvironmentType(ServiceCtx context)
  308. {
  309. throw new ServiceNotImplementedException(this, context);
  310. }
  311. [CommandHipc(102)] // 10.0.0+
  312. // DeleteApplicationServerEnvironmentType()
  313. public ResultCode DeleteApplicationServerEnvironmentType(ServiceCtx context)
  314. {
  315. throw new ServiceNotImplementedException(this, context);
  316. }
  317. }
  318. }