summaryrefslogtreecommitdiff
path: root/src/core/hle/service
diff options
context:
space:
mode:
authorGravatar FearlessTobi2022-07-30 05:58:23 +0200
committerGravatar FearlessTobi2022-08-15 20:25:42 +0200
commitf80c7c4cd5c090b9a31f89a0eb3d86cbe928c50b (patch)
treead359908ba2d3cd003082b39cc7217b61e5b18f6 /src/core/hle/service
parentweb_service: Correct jwt issuer string (diff)
downloadyuzu-f80c7c4cd5c090b9a31f89a0eb3d86cbe928c50b.tar.gz
yuzu-f80c7c4cd5c090b9a31f89a0eb3d86cbe928c50b.tar.xz
yuzu-f80c7c4cd5c090b9a31f89a0eb3d86cbe928c50b.zip
core, network: Add ability to proxy socket packets
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/nifm/nifm.cpp341
-rw-r--r--src/core/hle/service/nifm/nifm.h27
-rw-r--r--src/core/hle/service/sockets/bsd.cpp40
-rw-r--r--src/core/hle/service/sockets/bsd.h13
-rw-r--r--src/core/hle/service/sockets/sockets.h6
-rw-r--r--src/core/hle/service/sockets/sockets_translate.cpp2
6 files changed, 257 insertions, 172 deletions
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 2889973e4..42ed17187 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -6,7 +6,6 @@
6#include "core/hle/kernel/k_event.h" 6#include "core/hle/kernel/k_event.h"
7#include "core/hle/service/kernel_helpers.h" 7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/nifm/nifm.h" 8#include "core/hle/service/nifm/nifm.h"
9#include "core/hle/service/service.h"
10 9
11namespace { 10namespace {
12 11
@@ -271,213 +270,227 @@ public:
271 } 270 }
272}; 271};
273 272
274class IGeneralService final : public ServiceFramework<IGeneralService> { 273void IGeneralService::GetClientId(Kernel::HLERequestContext& ctx) {
275public: 274 static constexpr u32 client_id = 1;
276 explicit IGeneralService(Core::System& system_); 275 LOG_WARNING(Service_NIFM, "(STUBBED) called");
277 276
278private: 277 IPC::ResponseBuilder rb{ctx, 4};
279 void GetClientId(Kernel::HLERequestContext& ctx) { 278 rb.Push(ResultSuccess);
280 static constexpr u32 client_id = 1; 279 rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
281 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 280}
282 281
283 IPC::ResponseBuilder rb{ctx, 4}; 282void IGeneralService::CreateScanRequest(Kernel::HLERequestContext& ctx) {
284 rb.Push(ResultSuccess); 283 LOG_DEBUG(Service_NIFM, "called");
285 rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
286 }
287 284
288 void CreateScanRequest(Kernel::HLERequestContext& ctx) { 285 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
289 LOG_DEBUG(Service_NIFM, "called");
290 286
291 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 287 rb.Push(ResultSuccess);
288 rb.PushIpcInterface<IScanRequest>(system);
289}
292 290
293 rb.Push(ResultSuccess); 291void IGeneralService::CreateRequest(Kernel::HLERequestContext& ctx) {
294 rb.PushIpcInterface<IScanRequest>(system); 292 LOG_DEBUG(Service_NIFM, "called");
295 }
296 293
297 void CreateRequest(Kernel::HLERequestContext& ctx) { 294 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
298 LOG_DEBUG(Service_NIFM, "called");
299 295
300 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 296 rb.Push(ResultSuccess);
297 rb.PushIpcInterface<IRequest>(system);
298}
301 299
302 rb.Push(ResultSuccess); 300void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
303 rb.PushIpcInterface<IRequest>(system); 301 LOG_WARNING(Service_NIFM, "(STUBBED) called");
304 }
305 302
306 void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { 303 const auto net_iface = Network::GetSelectedNetworkInterface();
307 LOG_WARNING(Service_NIFM, "(STUBBED) called");
308 304
309 const auto net_iface = Network::GetSelectedNetworkInterface(); 305 SfNetworkProfileData network_profile_data = [&net_iface] {
310 306 if (!net_iface) {
311 const SfNetworkProfileData network_profile_data = [&net_iface] { 307 return SfNetworkProfileData{};
312 if (!net_iface) { 308 }
313 return SfNetworkProfileData{}; 309
314 } 310 return SfNetworkProfileData{
315 311 .ip_setting_data{
316 return SfNetworkProfileData{ 312 .ip_address_setting{
317 .ip_setting_data{ 313 .is_automatic{true},
318 .ip_address_setting{ 314 .current_address{Network::TranslateIPv4(net_iface->ip_address)},
319 .is_automatic{true}, 315 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
320 .current_address{Network::TranslateIPv4(net_iface->ip_address)}, 316 .gateway{Network::TranslateIPv4(net_iface->gateway)},
321 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
322 .gateway{Network::TranslateIPv4(net_iface->gateway)},
323 },
324 .dns_setting{
325 .is_automatic{true},
326 .primary_dns{1, 1, 1, 1},
327 .secondary_dns{1, 0, 0, 1},
328 },
329 .proxy_setting{
330 .enabled{false},
331 .port{},
332 .proxy_server{},
333 .automatic_auth_enabled{},
334 .user{},
335 .password{},
336 },
337 .mtu{1500},
338 }, 317 },
339 .uuid{0xdeadbeef, 0xdeadbeef}, 318 .dns_setting{
340 .network_name{"yuzu Network"}, 319 .is_automatic{true},
341 .wireless_setting_data{ 320 .primary_dns{1, 1, 1, 1},
342 .ssid_length{12}, 321 .secondary_dns{1, 0, 0, 1},
343 .ssid{"yuzu Network"},
344 .passphrase{"yuzupassword"},
345 }, 322 },
346 }; 323 .proxy_setting{
347 }(); 324 .enabled{false},
348 325 .port{},
349 ctx.WriteBuffer(network_profile_data); 326 .proxy_server{},
327 .automatic_auth_enabled{},
328 .user{},
329 .password{},
330 },
331 .mtu{1500},
332 },
333 .uuid{0xdeadbeef, 0xdeadbeef},
334 .network_name{"yuzu Network"},
335 .wireless_setting_data{
336 .ssid_length{12},
337 .ssid{"yuzu Network"},
338 .passphrase{"yuzupassword"},
339 },
340 };
341 }();
350 342
351 IPC::ResponseBuilder rb{ctx, 2}; 343 // When we're connected to a room, spoof the hosts IP address
352 rb.Push(ResultSuccess); 344 if (auto room_member = network.GetRoomMember().lock()) {
345 if (room_member->IsConnected()) {
346 network_profile_data.ip_setting_data.ip_address_setting.current_address =
347 room_member->GetFakeIpAddress();
348 }
353 } 349 }
354 350
355 void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { 351 ctx.WriteBuffer(network_profile_data);
356 LOG_WARNING(Service_NIFM, "(STUBBED) called");
357 352
358 IPC::ResponseBuilder rb{ctx, 2}; 353 IPC::ResponseBuilder rb{ctx, 2};
359 rb.Push(ResultSuccess); 354 rb.Push(ResultSuccess);
360 } 355}
361 356
362 void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { 357void IGeneralService::RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
363 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 358 LOG_WARNING(Service_NIFM, "(STUBBED) called");
364 359
365 auto ipv4 = Network::GetHostIPv4Address(); 360 IPC::ResponseBuilder rb{ctx, 2};
366 if (!ipv4) { 361 rb.Push(ResultSuccess);
367 LOG_ERROR(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); 362}
368 ipv4.emplace(Network::IPv4Address{0, 0, 0, 0});
369 }
370 363
371 IPC::ResponseBuilder rb{ctx, 3}; 364void IGeneralService::GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
372 rb.Push(ResultSuccess); 365 LOG_WARNING(Service_NIFM, "(STUBBED) called");
373 rb.PushRaw(*ipv4); 366
367 auto ipv4 = Network::GetHostIPv4Address();
368 if (!ipv4) {
369 LOG_ERROR(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0");
370 ipv4.emplace(Network::IPv4Address{0, 0, 0, 0});
374 } 371 }
375 372
376 void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { 373 // When we're connected to a room, spoof the hosts IP address
377 LOG_DEBUG(Service_NIFM, "called"); 374 if (auto room_member = network.GetRoomMember().lock()) {
375 if (room_member->IsConnected()) {
376 ipv4 = room_member->GetFakeIpAddress();
377 }
378 }
378 379
379 ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, 380 IPC::ResponseBuilder rb{ctx, 3};
380 "SfNetworkProfileData is not the correct size"); 381 rb.Push(ResultSuccess);
381 u128 uuid{}; 382 rb.PushRaw(*ipv4);
382 auto buffer = ctx.ReadBuffer(); 383}
383 std::memcpy(&uuid, buffer.data() + 8, sizeof(u128)); 384void IGeneralService::CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
385 LOG_DEBUG(Service_NIFM, "called");
384 386
385 IPC::ResponseBuilder rb{ctx, 6, 0, 1}; 387 ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, "SfNetworkProfileData is not the correct size");
388 u128 uuid{};
389 auto buffer = ctx.ReadBuffer();
390 std::memcpy(&uuid, buffer.data() + 8, sizeof(u128));
386 391
387 rb.Push(ResultSuccess); 392 IPC::ResponseBuilder rb{ctx, 6, 0, 1};
388 rb.PushIpcInterface<INetworkProfile>(system);
389 rb.PushRaw<u128>(uuid);
390 }
391 393
392 void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { 394 rb.Push(ResultSuccess);
393 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 395 rb.PushIpcInterface<INetworkProfile>(system);
396 rb.PushRaw<u128>(uuid);
397}
394 398
395 struct IpConfigInfo { 399void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
396 IpAddressSetting ip_address_setting{}; 400 LOG_WARNING(Service_NIFM, "(STUBBED) called");
397 DnsSetting dns_setting{};
398 };
399 static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
400 "IpConfigInfo has incorrect size.");
401 401
402 const auto net_iface = Network::GetSelectedNetworkInterface(); 402 struct IpConfigInfo {
403 IpAddressSetting ip_address_setting{};
404 DnsSetting dns_setting{};
405 };
406 static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
407 "IpConfigInfo has incorrect size.");
403 408
404 const IpConfigInfo ip_config_info = [&net_iface] { 409 const auto net_iface = Network::GetSelectedNetworkInterface();
405 if (!net_iface) {
406 return IpConfigInfo{};
407 }
408 410
409 return IpConfigInfo{ 411 IpConfigInfo ip_config_info = [&net_iface] {
410 .ip_address_setting{ 412 if (!net_iface) {
411 .is_automatic{true}, 413 return IpConfigInfo{};
412 .current_address{Network::TranslateIPv4(net_iface->ip_address)}, 414 }
413 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
414 .gateway{Network::TranslateIPv4(net_iface->gateway)},
415 },
416 .dns_setting{
417 .is_automatic{true},
418 .primary_dns{1, 1, 1, 1},
419 .secondary_dns{1, 0, 0, 1},
420 },
421 };
422 }();
423 415
424 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; 416 return IpConfigInfo{
425 rb.Push(ResultSuccess); 417 .ip_address_setting{
426 rb.PushRaw<IpConfigInfo>(ip_config_info); 418 .is_automatic{true},
419 .current_address{Network::TranslateIPv4(net_iface->ip_address)},
420 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
421 .gateway{Network::TranslateIPv4(net_iface->gateway)},
422 },
423 .dns_setting{
424 .is_automatic{true},
425 .primary_dns{1, 1, 1, 1},
426 .secondary_dns{1, 0, 0, 1},
427 },
428 };
429 }();
430
431 // When we're connected to a room, spoof the hosts IP address
432 if (auto room_member = network.GetRoomMember().lock()) {
433 if (room_member->IsConnected()) {
434 ip_config_info.ip_address_setting.current_address = room_member->GetFakeIpAddress();
435 }
427 } 436 }
428 437
429 void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) { 438 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)};
430 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 439 rb.Push(ResultSuccess);
440 rb.PushRaw<IpConfigInfo>(ip_config_info);
441}
431 442
432 IPC::ResponseBuilder rb{ctx, 3}; 443void IGeneralService::IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
433 rb.Push(ResultSuccess); 444 LOG_WARNING(Service_NIFM, "(STUBBED) called");
434 rb.Push<u8>(0);
435 }
436 445
437 void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) { 446 IPC::ResponseBuilder rb{ctx, 3};
438 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 447 rb.Push(ResultSuccess);
448 rb.Push<u8>(1);
449}
439 450
440 struct Output { 451void IGeneralService::GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) {
441 InternetConnectionType type{InternetConnectionType::WiFi}; 452 LOG_WARNING(Service_NIFM, "(STUBBED) called");
442 u8 wifi_strength{3};
443 InternetConnectionStatus state{InternetConnectionStatus::Connected};
444 };
445 static_assert(sizeof(Output) == 0x3, "Output has incorrect size.");
446 453
447 constexpr Output out{}; 454 struct Output {
455 InternetConnectionType type{InternetConnectionType::WiFi};
456 u8 wifi_strength{3};
457 InternetConnectionStatus state{InternetConnectionStatus::Connected};
458 };
459 static_assert(sizeof(Output) == 0x3, "Output has incorrect size.");
448 460
449 IPC::ResponseBuilder rb{ctx, 3}; 461 constexpr Output out{};
450 rb.Push(ResultSuccess);
451 rb.PushRaw(out);
452 }
453 462
454 void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) { 463 IPC::ResponseBuilder rb{ctx, 3};
455 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 464 rb.Push(ResultSuccess);
465 rb.PushRaw(out);
466}
456 467
457 IPC::ResponseBuilder rb{ctx, 3}; 468void IGeneralService::IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
458 rb.Push(ResultSuccess); 469 LOG_WARNING(Service_NIFM, "(STUBBED) called");
459 if (Network::GetHostIPv4Address().has_value()) { 470
460 rb.Push<u8>(1); 471 IPC::ResponseBuilder rb{ctx, 3};
461 } else { 472 rb.Push(ResultSuccess);
462 rb.Push<u8>(0); 473 if (Network::GetHostIPv4Address().has_value()) {
463 } 474 rb.Push<u8>(1);
475 } else {
476 rb.Push<u8>(0);
464 } 477 }
478}
465 479
466 void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { 480void IGeneralService::IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
467 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 481 LOG_ERROR(Service_NIFM, "(STUBBED) called");
468 482
469 IPC::ResponseBuilder rb{ctx, 3}; 483 IPC::ResponseBuilder rb{ctx, 3};
470 rb.Push(ResultSuccess); 484 rb.Push(ResultSuccess);
471 if (Network::GetHostIPv4Address().has_value()) { 485 if (Network::GetHostIPv4Address().has_value()) {
472 rb.Push<u8>(1); 486 rb.Push<u8>(1);
473 } else { 487 } else {
474 rb.Push<u8>(0); 488 rb.Push<u8>(0);
475 }
476 } 489 }
477}; 490}
478 491
479IGeneralService::IGeneralService(Core::System& system_) 492IGeneralService::IGeneralService(Core::System& system_)
480 : ServiceFramework{system_, "IGeneralService"} { 493 : ServiceFramework{system_, "IGeneralService"}, network{system_.GetRoomNetwork()} {
481 // clang-format off 494 // clang-format off
482 static const FunctionInfo functions[] = { 495 static const FunctionInfo functions[] = {
483 {1, &IGeneralService::GetClientId, "GetClientId"}, 496 {1, &IGeneralService::GetClientId, "GetClientId"},
@@ -528,6 +541,8 @@ IGeneralService::IGeneralService(Core::System& system_)
528 RegisterHandlers(functions); 541 RegisterHandlers(functions);
529} 542}
530 543
544IGeneralService::~IGeneralService() = default;
545
531class NetworkInterface final : public ServiceFramework<NetworkInterface> { 546class NetworkInterface final : public ServiceFramework<NetworkInterface> {
532public: 547public:
533 explicit NetworkInterface(const char* name, Core::System& system_) 548 explicit NetworkInterface(const char* name, Core::System& system_)
diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h
index 5f62d0014..48161be28 100644
--- a/src/core/hle/service/nifm/nifm.h
+++ b/src/core/hle/service/nifm/nifm.h
@@ -3,6 +3,11 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/service.h"
7#include "network/network.h"
8#include "network/room.h"
9#include "network/room_member.h"
10
6namespace Core { 11namespace Core {
7class System; 12class System;
8} 13}
@@ -16,4 +21,26 @@ namespace Service::NIFM {
16/// Registers all NIFM services with the specified service manager. 21/// Registers all NIFM services with the specified service manager.
17void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); 22void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
18 23
24class IGeneralService final : public ServiceFramework<IGeneralService> {
25public:
26 explicit IGeneralService(Core::System& system_);
27 ~IGeneralService() override;
28
29private:
30 void GetClientId(Kernel::HLERequestContext& ctx);
31 void CreateScanRequest(Kernel::HLERequestContext& ctx);
32 void CreateRequest(Kernel::HLERequestContext& ctx);
33 void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx);
34 void RemoveNetworkProfile(Kernel::HLERequestContext& ctx);
35 void GetCurrentIpAddress(Kernel::HLERequestContext& ctx);
36 void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx);
37 void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx);
38 void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx);
39 void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx);
40 void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx);
41 void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx);
42
43 Network::RoomNetwork& network;
44};
45
19} // namespace Service::NIFM 46} // namespace Service::NIFM
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index c7194731e..e08c3cb67 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -9,12 +9,16 @@
9#include <fmt/format.h> 9#include <fmt/format.h>
10 10
11#include "common/microprofile.h" 11#include "common/microprofile.h"
12#include "common/socket_types.h"
13#include "core/core.h"
12#include "core/hle/ipc_helpers.h" 14#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/k_thread.h" 15#include "core/hle/kernel/k_thread.h"
14#include "core/hle/service/sockets/bsd.h" 16#include "core/hle/service/sockets/bsd.h"
15#include "core/hle/service/sockets/sockets_translate.h" 17#include "core/hle/service/sockets/sockets_translate.h"
16#include "core/internal_network/network.h" 18#include "core/internal_network/network.h"
19#include "core/internal_network/socket_proxy.h"
17#include "core/internal_network/sockets.h" 20#include "core/internal_network/sockets.h"
21#include "network/network.h"
18 22
19namespace Service::Sockets { 23namespace Service::Sockets {
20 24
@@ -472,7 +476,13 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
472 476
473 LOG_INFO(Service, "New socket fd={}", fd); 477 LOG_INFO(Service, "New socket fd={}", fd);
474 478
475 descriptor.socket = std::make_unique<Network::Socket>(); 479 auto room_member = room_network.GetRoomMember().lock();
480 if (room_member && room_member->IsConnected()) {
481 descriptor.socket = std::make_unique<Network::ProxySocket>(room_network);
482 } else {
483 descriptor.socket = std::make_unique<Network::Socket>();
484 }
485
476 descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(type, protocol)); 486 descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(type, protocol));
477 descriptor.is_connection_based = IsConnectionBased(type); 487 descriptor.is_connection_based = IsConnectionBased(type);
478 488
@@ -648,7 +658,7 @@ std::pair<s32, Errno> BSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
648 ASSERT(arg == 0); 658 ASSERT(arg == 0);
649 return {descriptor.flags, Errno::SUCCESS}; 659 return {descriptor.flags, Errno::SUCCESS};
650 case FcntlCmd::SETFL: { 660 case FcntlCmd::SETFL: {
651 const bool enable = (arg & FLAG_O_NONBLOCK) != 0; 661 const bool enable = (arg & Network::FLAG_O_NONBLOCK) != 0;
652 const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable)); 662 const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable));
653 if (bsd_errno != Errno::SUCCESS) { 663 if (bsd_errno != Errno::SUCCESS) {
654 return {-1, bsd_errno}; 664 return {-1, bsd_errno};
@@ -669,7 +679,7 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con
669 return Errno::BADF; 679 return Errno::BADF;
670 } 680 }
671 681
672 Network::Socket* const socket = file_descriptors[fd]->socket.get(); 682 Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
673 683
674 if (optname == OptName::LINGER) { 684 if (optname == OptName::LINGER) {
675 ASSERT(optlen == sizeof(Linger)); 685 ASSERT(optlen == sizeof(Linger));
@@ -724,6 +734,8 @@ std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message)
724 FileDescriptor& descriptor = *file_descriptors[fd]; 734 FileDescriptor& descriptor = *file_descriptors[fd];
725 735
726 // Apply flags 736 // Apply flags
737 using Network::FLAG_MSG_DONTWAIT;
738 using Network::FLAG_O_NONBLOCK;
727 if ((flags & FLAG_MSG_DONTWAIT) != 0) { 739 if ((flags & FLAG_MSG_DONTWAIT) != 0) {
728 flags &= ~FLAG_MSG_DONTWAIT; 740 flags &= ~FLAG_MSG_DONTWAIT;
729 if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { 741 if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
@@ -759,6 +771,8 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
759 } 771 }
760 772
761 // Apply flags 773 // Apply flags
774 using Network::FLAG_MSG_DONTWAIT;
775 using Network::FLAG_O_NONBLOCK;
762 if ((flags & FLAG_MSG_DONTWAIT) != 0) { 776 if ((flags & FLAG_MSG_DONTWAIT) != 0) {
763 flags &= ~FLAG_MSG_DONTWAIT; 777 flags &= ~FLAG_MSG_DONTWAIT;
764 if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { 778 if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
@@ -857,8 +871,19 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co
857 rb.PushEnum(bsd_errno); 871 rb.PushEnum(bsd_errno);
858} 872}
859 873
874void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
875 for (auto& optional_descriptor : file_descriptors) {
876 if (!optional_descriptor.has_value()) {
877 continue;
878 }
879 FileDescriptor& descriptor = *optional_descriptor;
880 descriptor.socket.get()->HandleProxyPacket(packet);
881 }
882}
883
860BSD::BSD(Core::System& system_, const char* name) 884BSD::BSD(Core::System& system_, const char* name)
861 : ServiceFramework{system_, name, ServiceThreadType::CreateNew} { 885 : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, room_network{
886 system_.GetRoomNetwork()} {
862 // clang-format off 887 // clang-format off
863 static const FunctionInfo functions[] = { 888 static const FunctionInfo functions[] = {
864 {0, &BSD::RegisterClient, "RegisterClient"}, 889 {0, &BSD::RegisterClient, "RegisterClient"},
@@ -899,6 +924,13 @@ BSD::BSD(Core::System& system_, const char* name)
899 // clang-format on 924 // clang-format on
900 925
901 RegisterHandlers(functions); 926 RegisterHandlers(functions);
927
928 if (auto room_member = room_network.GetRoomMember().lock()) {
929 proxy_packet_received = room_member->BindOnProxyPacketReceived(
930 [this](const Network::ProxyPacket& packet) { OnProxyPacketReceived(packet); });
931 } else {
932 LOG_ERROR(Service, "Network isn't initalized");
933 }
902} 934}
903 935
904BSD::~BSD() = default; 936BSD::~BSD() = default;
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 9ea36428d..81e855e0f 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -7,14 +7,17 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/socket_types.h"
10#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
11#include "core/hle/service/sockets/sockets.h" 12#include "core/hle/service/sockets/sockets.h"
13#include "network/network.h"
12 14
13namespace Core { 15namespace Core {
14class System; 16class System;
15} 17}
16 18
17namespace Network { 19namespace Network {
20class SocketBase;
18class Socket; 21class Socket;
19} // namespace Network 22} // namespace Network
20 23
@@ -30,7 +33,7 @@ private:
30 static constexpr size_t MAX_FD = 128; 33 static constexpr size_t MAX_FD = 128;
31 34
32 struct FileDescriptor { 35 struct FileDescriptor {
33 std::unique_ptr<Network::Socket> socket; 36 std::unique_ptr<Network::SocketBase> socket;
34 s32 flags = 0; 37 s32 flags = 0;
35 bool is_connection_based = false; 38 bool is_connection_based = false;
36 }; 39 };
@@ -165,6 +168,14 @@ private:
165 void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; 168 void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept;
166 169
167 std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; 170 std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors;
171
172 Network::RoomNetwork& room_network;
173
174 /// Callback to parse and handle a received wifi packet.
175 void OnProxyPacketReceived(const Network::ProxyPacket& packet);
176
177 // Callback identifier for the OnProxyPacketReceived event.
178 Network::RoomMember::CallbackHandle<Network::ProxyPacket> proxy_packet_received;
168}; 179};
169 180
170class BSDCFG final : public ServiceFramework<BSDCFG> { 181class BSDCFG final : public ServiceFramework<BSDCFG> {
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h
index b735b00fc..31b7dad33 100644
--- a/src/core/hle/service/sockets/sockets.h
+++ b/src/core/hle/service/sockets/sockets.h
@@ -22,7 +22,9 @@ enum class Errno : u32 {
22 AGAIN = 11, 22 AGAIN = 11,
23 INVAL = 22, 23 INVAL = 22,
24 MFILE = 24, 24 MFILE = 24,
25 MSGSIZE = 90,
25 NOTCONN = 107, 26 NOTCONN = 107,
27 TIMEDOUT = 110,
26}; 28};
27 29
28enum class Domain : u32 { 30enum class Domain : u32 {
@@ -96,10 +98,6 @@ struct Linger {
96 u32 linger; 98 u32 linger;
97}; 99};
98 100
99constexpr u32 FLAG_MSG_DONTWAIT = 0x80;
100
101constexpr u32 FLAG_O_NONBLOCK = 0x800;
102
103/// Registers all Sockets services with the specified service manager. 101/// Registers all Sockets services with the specified service manager.
104void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); 102void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
105 103
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp
index 2db10ec81..023aa0486 100644
--- a/src/core/hle/service/sockets/sockets_translate.cpp
+++ b/src/core/hle/service/sockets/sockets_translate.cpp
@@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) {
25 return Errno::MFILE; 25 return Errno::MFILE;
26 case Network::Errno::NOTCONN: 26 case Network::Errno::NOTCONN:
27 return Errno::NOTCONN; 27 return Errno::NOTCONN;
28 case Network::Errno::TIMEDOUT:
29 return Errno::TIMEDOUT;
28 default: 30 default:
29 UNIMPLEMENTED_MSG("Unimplemented errno={}", value); 31 UNIMPLEMENTED_MSG("Unimplemented errno={}", value);
30 return Errno::SUCCESS; 32 return Errno::SUCCESS;