ldn.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <memory>
  4. #include "core/core.h"
  5. #include "core/hle/service/ldn/lan_discovery.h"
  6. #include "core/hle/service/ldn/ldn.h"
  7. #include "core/hle/service/ldn/ldn_results.h"
  8. #include "core/hle/service/ldn/ldn_types.h"
  9. #include "core/internal_network/network.h"
  10. #include "core/internal_network/network_interface.h"
  11. #include "network/network.h"
  12. // This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
  13. #undef CreateEvent
  14. namespace Service::LDN {
  15. class IMonitorService final : public ServiceFramework<IMonitorService> {
  16. public:
  17. explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} {
  18. // clang-format off
  19. static const FunctionInfo functions[] = {
  20. {0, nullptr, "GetStateForMonitor"},
  21. {1, nullptr, "GetNetworkInfoForMonitor"},
  22. {2, nullptr, "GetIpv4AddressForMonitor"},
  23. {3, nullptr, "GetDisconnectReasonForMonitor"},
  24. {4, nullptr, "GetSecurityParameterForMonitor"},
  25. {5, nullptr, "GetNetworkConfigForMonitor"},
  26. {100, nullptr, "InitializeMonitor"},
  27. {101, nullptr, "FinalizeMonitor"},
  28. };
  29. // clang-format on
  30. RegisterHandlers(functions);
  31. }
  32. };
  33. class LDNM final : public ServiceFramework<LDNM> {
  34. public:
  35. explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
  36. // clang-format off
  37. static const FunctionInfo functions[] = {
  38. {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
  39. };
  40. // clang-format on
  41. RegisterHandlers(functions);
  42. }
  43. void CreateMonitorService(Kernel::HLERequestContext& ctx) {
  44. LOG_DEBUG(Service_LDN, "called");
  45. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  46. rb.Push(ResultSuccess);
  47. rb.PushIpcInterface<IMonitorService>(system);
  48. }
  49. };
  50. class ISystemLocalCommunicationService final
  51. : public ServiceFramework<ISystemLocalCommunicationService> {
  52. public:
  53. explicit ISystemLocalCommunicationService(Core::System& system_)
  54. : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
  55. // clang-format off
  56. static const FunctionInfo functions[] = {
  57. {0, nullptr, "GetState"},
  58. {1, nullptr, "GetNetworkInfo"},
  59. {2, nullptr, "GetIpv4Address"},
  60. {3, nullptr, "GetDisconnectReason"},
  61. {4, nullptr, "GetSecurityParameter"},
  62. {5, nullptr, "GetNetworkConfig"},
  63. {100, nullptr, "AttachStateChangeEvent"},
  64. {101, nullptr, "GetNetworkInfoLatestUpdate"},
  65. {102, nullptr, "Scan"},
  66. {103, nullptr, "ScanPrivate"},
  67. {104, nullptr, "SetWirelessControllerRestriction"},
  68. {200, nullptr, "OpenAccessPoint"},
  69. {201, nullptr, "CloseAccessPoint"},
  70. {202, nullptr, "CreateNetwork"},
  71. {203, nullptr, "CreateNetworkPrivate"},
  72. {204, nullptr, "DestroyNetwork"},
  73. {205, nullptr, "Reject"},
  74. {206, nullptr, "SetAdvertiseData"},
  75. {207, nullptr, "SetStationAcceptPolicy"},
  76. {208, nullptr, "AddAcceptFilterEntry"},
  77. {209, nullptr, "ClearAcceptFilter"},
  78. {300, nullptr, "OpenStation"},
  79. {301, nullptr, "CloseStation"},
  80. {302, nullptr, "Connect"},
  81. {303, nullptr, "ConnectPrivate"},
  82. {304, nullptr, "Disconnect"},
  83. {400, nullptr, "InitializeSystem"},
  84. {401, nullptr, "FinalizeSystem"},
  85. {402, nullptr, "SetOperationMode"},
  86. {403, nullptr, "InitializeSystem2"},
  87. };
  88. // clang-format on
  89. RegisterHandlers(functions);
  90. }
  91. };
  92. class IUserLocalCommunicationService final
  93. : public ServiceFramework<IUserLocalCommunicationService> {
  94. public:
  95. explicit IUserLocalCommunicationService(Core::System& system_)
  96. : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
  97. service_context{system, "IUserLocalCommunicationService"},
  98. room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
  99. // clang-format off
  100. static const FunctionInfo functions[] = {
  101. {0, &IUserLocalCommunicationService::GetState, "GetState"},
  102. {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
  103. {2, &IUserLocalCommunicationService::GetIpv4Address, "GetIpv4Address"},
  104. {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
  105. {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
  106. {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
  107. {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
  108. {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
  109. {102, &IUserLocalCommunicationService::Scan, "Scan"},
  110. {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
  111. {104, &IUserLocalCommunicationService::SetWirelessControllerRestriction, "SetWirelessControllerRestriction"},
  112. {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
  113. {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
  114. {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
  115. {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
  116. {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
  117. {205, nullptr, "Reject"},
  118. {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
  119. {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
  120. {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
  121. {209, nullptr, "ClearAcceptFilter"},
  122. {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
  123. {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
  124. {302, &IUserLocalCommunicationService::Connect, "Connect"},
  125. {303, nullptr, "ConnectPrivate"},
  126. {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
  127. {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
  128. {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
  129. {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
  130. };
  131. // clang-format on
  132. RegisterHandlers(functions);
  133. state_change_event =
  134. service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
  135. }
  136. ~IUserLocalCommunicationService() {
  137. if (is_initialized) {
  138. if (auto room_member = room_network.GetRoomMember().lock()) {
  139. room_member->Unbind(ldn_packet_received);
  140. }
  141. }
  142. service_context.CloseEvent(state_change_event);
  143. }
  144. /// Callback to parse and handle a received LDN packet.
  145. void OnLDNPacketReceived(const Network::LDNPacket& packet) {
  146. lan_discovery.ReceivePacket(packet);
  147. }
  148. void OnEventFired() {
  149. state_change_event->Signal();
  150. }
  151. void GetState(Kernel::HLERequestContext& ctx) {
  152. State state = State::Error;
  153. if (is_initialized) {
  154. state = lan_discovery.GetState();
  155. }
  156. IPC::ResponseBuilder rb{ctx, 3};
  157. rb.Push(ResultSuccess);
  158. rb.PushEnum(state);
  159. }
  160. void GetNetworkInfo(Kernel::HLERequestContext& ctx) {
  161. const auto write_buffer_size = ctx.GetWriteBufferSize();
  162. if (write_buffer_size != sizeof(NetworkInfo)) {
  163. LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
  164. IPC::ResponseBuilder rb{ctx, 2};
  165. rb.Push(ResultBadInput);
  166. return;
  167. }
  168. NetworkInfo network_info{};
  169. const auto rc = lan_discovery.GetNetworkInfo(network_info);
  170. if (rc.IsError()) {
  171. LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
  172. IPC::ResponseBuilder rb{ctx, 2};
  173. rb.Push(rc);
  174. return;
  175. }
  176. ctx.WriteBuffer<NetworkInfo>(network_info);
  177. IPC::ResponseBuilder rb{ctx, 2};
  178. rb.Push(ResultSuccess);
  179. }
  180. void GetIpv4Address(Kernel::HLERequestContext& ctx) {
  181. const auto network_interface = Network::GetSelectedNetworkInterface();
  182. if (!network_interface) {
  183. LOG_ERROR(Service_LDN, "No network interface available");
  184. IPC::ResponseBuilder rb{ctx, 2};
  185. rb.Push(ResultNoIpAddress);
  186. return;
  187. }
  188. Ipv4Address current_address{Network::TranslateIPv4(network_interface->ip_address)};
  189. Ipv4Address subnet_mask{Network::TranslateIPv4(network_interface->subnet_mask)};
  190. // When we're connected to a room, spoof the hosts IP address
  191. if (auto room_member = room_network.GetRoomMember().lock()) {
  192. if (room_member->IsConnected()) {
  193. current_address = room_member->GetFakeIpAddress();
  194. }
  195. }
  196. std::reverse(std::begin(current_address), std::end(current_address)); // ntohl
  197. std::reverse(std::begin(subnet_mask), std::end(subnet_mask)); // ntohl
  198. IPC::ResponseBuilder rb{ctx, 4};
  199. rb.Push(ResultSuccess);
  200. rb.PushRaw(current_address);
  201. rb.PushRaw(subnet_mask);
  202. }
  203. void GetDisconnectReason(Kernel::HLERequestContext& ctx) {
  204. IPC::ResponseBuilder rb{ctx, 3};
  205. rb.Push(ResultSuccess);
  206. rb.PushEnum(lan_discovery.GetDisconnectReason());
  207. }
  208. void GetSecurityParameter(Kernel::HLERequestContext& ctx) {
  209. SecurityParameter security_parameter{};
  210. NetworkInfo info{};
  211. const Result rc = lan_discovery.GetNetworkInfo(info);
  212. if (rc.IsError()) {
  213. LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
  214. IPC::ResponseBuilder rb{ctx, 2};
  215. rb.Push(rc);
  216. return;
  217. }
  218. security_parameter.session_id = info.network_id.session_id;
  219. std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
  220. sizeof(SecurityParameter::data));
  221. IPC::ResponseBuilder rb{ctx, 10};
  222. rb.Push(rc);
  223. rb.PushRaw<SecurityParameter>(security_parameter);
  224. }
  225. void GetNetworkConfig(Kernel::HLERequestContext& ctx) {
  226. NetworkConfig config{};
  227. NetworkInfo info{};
  228. const Result rc = lan_discovery.GetNetworkInfo(info);
  229. if (rc.IsError()) {
  230. LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
  231. IPC::ResponseBuilder rb{ctx, 2};
  232. rb.Push(rc);
  233. return;
  234. }
  235. config.intent_id = info.network_id.intent_id;
  236. config.channel = info.common.channel;
  237. config.node_count_max = info.ldn.node_count_max;
  238. config.local_communication_version = info.ldn.nodes[0].local_communication_version;
  239. IPC::ResponseBuilder rb{ctx, 10};
  240. rb.Push(rc);
  241. rb.PushRaw<NetworkConfig>(config);
  242. }
  243. void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
  244. LOG_INFO(Service_LDN, "called");
  245. IPC::ResponseBuilder rb{ctx, 2, 1};
  246. rb.Push(ResultSuccess);
  247. rb.PushCopyObjects(state_change_event->GetReadableEvent());
  248. }
  249. void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
  250. const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
  251. const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1);
  252. if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
  253. LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", network_buffer_size,
  254. node_buffer_count);
  255. IPC::ResponseBuilder rb{ctx, 2};
  256. rb.Push(ResultBadInput);
  257. return;
  258. }
  259. NetworkInfo info{};
  260. std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
  261. const auto rc = lan_discovery.GetNetworkInfo(info, latest_update, latest_update.size());
  262. if (rc.IsError()) {
  263. LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
  264. IPC::ResponseBuilder rb{ctx, 2};
  265. rb.Push(rc);
  266. return;
  267. }
  268. ctx.WriteBuffer(info, 0);
  269. ctx.WriteBuffer(latest_update, 1);
  270. IPC::ResponseBuilder rb{ctx, 2};
  271. rb.Push(ResultSuccess);
  272. }
  273. void Scan(Kernel::HLERequestContext& ctx) {
  274. ScanImpl(ctx);
  275. }
  276. void ScanPrivate(Kernel::HLERequestContext& ctx) {
  277. ScanImpl(ctx, true);
  278. }
  279. void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
  280. IPC::RequestParser rp{ctx};
  281. const auto channel{rp.PopEnum<WifiChannel>()};
  282. const auto scan_filter{rp.PopRaw<ScanFilter>()};
  283. const std::size_t network_info_size = ctx.GetWriteBufferNumElements<NetworkInfo>();
  284. if (network_info_size == 0) {
  285. LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
  286. IPC::ResponseBuilder rb{ctx, 2};
  287. rb.Push(ResultBadInput);
  288. return;
  289. }
  290. u16 count = 0;
  291. std::vector<NetworkInfo> network_infos(network_info_size);
  292. Result rc = lan_discovery.Scan(network_infos, count, scan_filter);
  293. LOG_INFO(Service_LDN,
  294. "called, channel={}, filter_scan_flag={}, filter_network_type={}, is_private={}",
  295. channel, scan_filter.flag, scan_filter.network_type, is_private);
  296. ctx.WriteBuffer(network_infos);
  297. IPC::ResponseBuilder rb{ctx, 3};
  298. rb.Push(rc);
  299. rb.Push<u32>(count);
  300. }
  301. void SetWirelessControllerRestriction(Kernel::HLERequestContext& ctx) {
  302. LOG_WARNING(Service_LDN, "(STUBBED) called");
  303. IPC::ResponseBuilder rb{ctx, 2};
  304. rb.Push(ResultSuccess);
  305. }
  306. void OpenAccessPoint(Kernel::HLERequestContext& ctx) {
  307. LOG_INFO(Service_LDN, "called");
  308. IPC::ResponseBuilder rb{ctx, 2};
  309. rb.Push(lan_discovery.OpenAccessPoint());
  310. }
  311. void CloseAccessPoint(Kernel::HLERequestContext& ctx) {
  312. LOG_INFO(Service_LDN, "called");
  313. IPC::ResponseBuilder rb{ctx, 2};
  314. rb.Push(lan_discovery.CloseAccessPoint());
  315. }
  316. void CreateNetwork(Kernel::HLERequestContext& ctx) {
  317. LOG_INFO(Service_LDN, "called");
  318. CreateNetworkImpl(ctx);
  319. }
  320. void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
  321. LOG_INFO(Service_LDN, "called");
  322. CreateNetworkImpl(ctx, true);
  323. }
  324. void CreateNetworkImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
  325. IPC::RequestParser rp{ctx};
  326. const auto security_config{rp.PopRaw<SecurityConfig>()};
  327. [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>()
  328. : SecurityParameter{}};
  329. const auto user_config{rp.PopRaw<UserConfig>()};
  330. rp.Pop<u32>(); // Padding
  331. const auto network_Config{rp.PopRaw<NetworkConfig>()};
  332. IPC::ResponseBuilder rb{ctx, 2};
  333. rb.Push(lan_discovery.CreateNetwork(security_config, user_config, network_Config));
  334. }
  335. void DestroyNetwork(Kernel::HLERequestContext& ctx) {
  336. LOG_INFO(Service_LDN, "called");
  337. IPC::ResponseBuilder rb{ctx, 2};
  338. rb.Push(lan_discovery.DestroyNetwork());
  339. }
  340. void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
  341. std::vector<u8> read_buffer = ctx.ReadBuffer();
  342. IPC::ResponseBuilder rb{ctx, 2};
  343. rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
  344. }
  345. void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
  346. LOG_WARNING(Service_LDN, "(STUBBED) called");
  347. IPC::ResponseBuilder rb{ctx, 2};
  348. rb.Push(ResultSuccess);
  349. }
  350. void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
  351. LOG_WARNING(Service_LDN, "(STUBBED) called");
  352. IPC::ResponseBuilder rb{ctx, 2};
  353. rb.Push(ResultSuccess);
  354. }
  355. void OpenStation(Kernel::HLERequestContext& ctx) {
  356. LOG_INFO(Service_LDN, "called");
  357. IPC::ResponseBuilder rb{ctx, 2};
  358. rb.Push(lan_discovery.OpenStation());
  359. }
  360. void CloseStation(Kernel::HLERequestContext& ctx) {
  361. LOG_INFO(Service_LDN, "called");
  362. IPC::ResponseBuilder rb{ctx, 2};
  363. rb.Push(lan_discovery.CloseStation());
  364. }
  365. void Connect(Kernel::HLERequestContext& ctx) {
  366. IPC::RequestParser rp{ctx};
  367. struct Parameters {
  368. SecurityConfig security_config;
  369. UserConfig user_config;
  370. u32 local_communication_version;
  371. u32 option;
  372. };
  373. static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
  374. const auto parameters{rp.PopRaw<Parameters>()};
  375. LOG_INFO(Service_LDN,
  376. "called, passphrase_size={}, security_mode={}, "
  377. "local_communication_version={}",
  378. parameters.security_config.passphrase_size,
  379. parameters.security_config.security_mode, parameters.local_communication_version);
  380. const std::vector<u8> read_buffer = ctx.ReadBuffer();
  381. if (read_buffer.size() != sizeof(NetworkInfo)) {
  382. LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
  383. IPC::ResponseBuilder rb{ctx, 2};
  384. rb.Push(ResultBadInput);
  385. return;
  386. }
  387. NetworkInfo network_info{};
  388. std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
  389. IPC::ResponseBuilder rb{ctx, 2};
  390. rb.Push(lan_discovery.Connect(network_info, parameters.user_config,
  391. static_cast<u16>(parameters.local_communication_version)));
  392. }
  393. void Disconnect(Kernel::HLERequestContext& ctx) {
  394. LOG_INFO(Service_LDN, "called");
  395. IPC::ResponseBuilder rb{ctx, 2};
  396. rb.Push(lan_discovery.Disconnect());
  397. }
  398. void Initialize(Kernel::HLERequestContext& ctx) {
  399. const auto rc = InitializeImpl(ctx);
  400. if (rc.IsError()) {
  401. LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
  402. }
  403. IPC::ResponseBuilder rb{ctx, 2};
  404. rb.Push(rc);
  405. }
  406. void Finalize(Kernel::HLERequestContext& ctx) {
  407. if (auto room_member = room_network.GetRoomMember().lock()) {
  408. room_member->Unbind(ldn_packet_received);
  409. }
  410. is_initialized = false;
  411. IPC::ResponseBuilder rb{ctx, 2};
  412. rb.Push(lan_discovery.Finalize());
  413. }
  414. void Initialize2(Kernel::HLERequestContext& ctx) {
  415. const auto rc = InitializeImpl(ctx);
  416. if (rc.IsError()) {
  417. LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
  418. }
  419. IPC::ResponseBuilder rb{ctx, 2};
  420. rb.Push(rc);
  421. }
  422. Result InitializeImpl(Kernel::HLERequestContext& ctx) {
  423. const auto network_interface = Network::GetSelectedNetworkInterface();
  424. if (!network_interface) {
  425. LOG_ERROR(Service_LDN, "No network interface is set");
  426. return ResultAirplaneModeEnabled;
  427. }
  428. if (auto room_member = room_network.GetRoomMember().lock()) {
  429. ldn_packet_received = room_member->BindOnLdnPacketReceived(
  430. [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
  431. } else {
  432. LOG_ERROR(Service_LDN, "Couldn't bind callback!");
  433. return ResultAirplaneModeEnabled;
  434. }
  435. lan_discovery.Initialize([&]() { OnEventFired(); });
  436. is_initialized = true;
  437. return ResultSuccess;
  438. }
  439. KernelHelpers::ServiceContext service_context;
  440. Kernel::KEvent* state_change_event;
  441. Network::RoomNetwork& room_network;
  442. LANDiscovery lan_discovery;
  443. // Callback identifier for the OnLDNPacketReceived event.
  444. Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
  445. bool is_initialized{};
  446. };
  447. class LDNS final : public ServiceFramework<LDNS> {
  448. public:
  449. explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
  450. // clang-format off
  451. static const FunctionInfo functions[] = {
  452. {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
  453. };
  454. // clang-format on
  455. RegisterHandlers(functions);
  456. }
  457. void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) {
  458. LOG_DEBUG(Service_LDN, "called");
  459. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  460. rb.Push(ResultSuccess);
  461. rb.PushIpcInterface<ISystemLocalCommunicationService>(system);
  462. }
  463. };
  464. class LDNU final : public ServiceFramework<LDNU> {
  465. public:
  466. explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
  467. // clang-format off
  468. static const FunctionInfo functions[] = {
  469. {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
  470. };
  471. // clang-format on
  472. RegisterHandlers(functions);
  473. }
  474. void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) {
  475. LOG_DEBUG(Service_LDN, "called");
  476. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  477. rb.Push(ResultSuccess);
  478. rb.PushIpcInterface<IUserLocalCommunicationService>(system);
  479. }
  480. };
  481. class INetworkService final : public ServiceFramework<INetworkService> {
  482. public:
  483. explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} {
  484. // clang-format off
  485. static const FunctionInfo functions[] = {
  486. {0, nullptr, "Initialize"},
  487. {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
  488. {264, nullptr, "GetNetworkInterfaceLastError"},
  489. {272, nullptr, "GetRole"},
  490. {280, nullptr, "GetAdvertiseData"},
  491. {288, nullptr, "GetGroupInfo"},
  492. {296, nullptr, "GetGroupInfo2"},
  493. {304, nullptr, "GetGroupOwner"},
  494. {312, nullptr, "GetIpConfig"},
  495. {320, nullptr, "GetLinkLevel"},
  496. {512, nullptr, "Scan"},
  497. {768, nullptr, "CreateGroup"},
  498. {776, nullptr, "DestroyGroup"},
  499. {784, nullptr, "SetAdvertiseData"},
  500. {1536, nullptr, "SendToOtherGroup"},
  501. {1544, nullptr, "RecvFromOtherGroup"},
  502. {1552, nullptr, "AddAcceptableGroupId"},
  503. {1560, nullptr, "ClearAcceptableGroupId"},
  504. };
  505. // clang-format on
  506. RegisterHandlers(functions);
  507. }
  508. };
  509. class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> {
  510. public:
  511. explicit INetworkServiceMonitor(Core::System& system_)
  512. : ServiceFramework{system_, "INetworkServiceMonitor"} {
  513. // clang-format off
  514. static const FunctionInfo functions[] = {
  515. {0, &INetworkServiceMonitor::Initialize, "Initialize"},
  516. {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
  517. {264, nullptr, "GetNetworkInterfaceLastError"},
  518. {272, nullptr, "GetRole"},
  519. {280, nullptr, "GetAdvertiseData"},
  520. {281, nullptr, "GetAdvertiseData2"},
  521. {288, nullptr, "GetGroupInfo"},
  522. {296, nullptr, "GetGroupInfo2"},
  523. {304, nullptr, "GetGroupOwner"},
  524. {312, nullptr, "GetIpConfig"},
  525. {320, nullptr, "GetLinkLevel"},
  526. {328, nullptr, "AttachJoinEvent"},
  527. {336, nullptr, "GetMembers"},
  528. };
  529. // clang-format on
  530. RegisterHandlers(functions);
  531. }
  532. void Initialize(Kernel::HLERequestContext& ctx) {
  533. LOG_WARNING(Service_LDN, "(STUBBED) called");
  534. IPC::ResponseBuilder rb{ctx, 2};
  535. rb.Push(ResultDisabled);
  536. }
  537. };
  538. class LP2PAPP final : public ServiceFramework<LP2PAPP> {
  539. public:
  540. explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} {
  541. // clang-format off
  542. static const FunctionInfo functions[] = {
  543. {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"},
  544. {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"},
  545. };
  546. // clang-format on
  547. RegisterHandlers(functions);
  548. }
  549. void CreateNetworkervice(Kernel::HLERequestContext& ctx) {
  550. IPC::RequestParser rp{ctx};
  551. const u64 reserved_input = rp.Pop<u64>();
  552. const u32 input = rp.Pop<u32>();
  553. LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
  554. input);
  555. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  556. rb.Push(ResultSuccess);
  557. rb.PushIpcInterface<INetworkService>(system);
  558. }
  559. void CreateMonitorService(Kernel::HLERequestContext& ctx) {
  560. IPC::RequestParser rp{ctx};
  561. const u64 reserved_input = rp.Pop<u64>();
  562. LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
  563. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  564. rb.Push(ResultSuccess);
  565. rb.PushIpcInterface<INetworkServiceMonitor>(system);
  566. }
  567. };
  568. class LP2PSYS final : public ServiceFramework<LP2PSYS> {
  569. public:
  570. explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} {
  571. // clang-format off
  572. static const FunctionInfo functions[] = {
  573. {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"},
  574. {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"},
  575. };
  576. // clang-format on
  577. RegisterHandlers(functions);
  578. }
  579. void CreateNetworkervice(Kernel::HLERequestContext& ctx) {
  580. IPC::RequestParser rp{ctx};
  581. const u64 reserved_input = rp.Pop<u64>();
  582. const u32 input = rp.Pop<u32>();
  583. LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
  584. input);
  585. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  586. rb.Push(ResultSuccess);
  587. rb.PushIpcInterface<INetworkService>(system);
  588. }
  589. void CreateMonitorService(Kernel::HLERequestContext& ctx) {
  590. IPC::RequestParser rp{ctx};
  591. const u64 reserved_input = rp.Pop<u64>();
  592. LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
  593. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  594. rb.Push(ResultSuccess);
  595. rb.PushIpcInterface<INetworkServiceMonitor>(system);
  596. }
  597. };
  598. void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
  599. std::make_shared<LDNM>(system)->InstallAsService(sm);
  600. std::make_shared<LDNS>(system)->InstallAsService(sm);
  601. std::make_shared<LDNU>(system)->InstallAsService(sm);
  602. std::make_shared<LP2PAPP>(system)->InstallAsService(sm);
  603. std::make_shared<LP2PSYS>(system)->InstallAsService(sm);
  604. }
  605. } // namespace Service::LDN