diff options
| -rw-r--r-- | src/citra_qt/debugger/wait_tree.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nwm/nwm_uds.cpp | 98 |
4 files changed, 112 insertions, 10 deletions
diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h index 06ef58ea7..2b38712b9 100644 --- a/src/citra_qt/debugger/wait_tree.h +++ b/src/citra_qt/debugger/wait_tree.h | |||
| @@ -18,7 +18,6 @@ class WaitObject; | |||
| 18 | class Event; | 18 | class Event; |
| 19 | class Mutex; | 19 | class Mutex; |
| 20 | class Semaphore; | 20 | class Semaphore; |
| 21 | class Session; | ||
| 22 | class Thread; | 21 | class Thread; |
| 23 | class Timer; | 22 | class Timer; |
| 24 | } | 23 | } |
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 6bc49ff64..fef97af1f 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/kernel/errors.h" | 8 | #include "core/hle/kernel/errors.h" |
| 9 | #include "core/hle/kernel/hle_ipc.h" | 9 | #include "core/hle/kernel/hle_ipc.h" |
| 10 | #include "core/hle/kernel/server_session.h" | 10 | #include "core/hle/kernel/server_session.h" |
| 11 | #include "core/hle/kernel/session.h" | ||
| 11 | 12 | ||
| 12 | namespace Kernel { | 13 | namespace Kernel { |
| 13 | 14 | ||
| @@ -16,9 +17,13 @@ ClientSession::~ClientSession() { | |||
| 16 | // This destructor will be called automatically when the last ClientSession handle is closed by | 17 | // This destructor will be called automatically when the last ClientSession handle is closed by |
| 17 | // the emulated application. | 18 | // the emulated application. |
| 18 | 19 | ||
| 19 | if (parent->server) { | 20 | // Local references to ServerSession and SessionRequestHandler are necessary to guarantee they |
| 20 | if (parent->server->hle_handler) | 21 | // will be kept alive until after ClientDisconnected() returns. |
| 21 | parent->server->hle_handler->ClientDisconnected(parent->server); | 22 | SharedPtr<ServerSession> server = parent->server; |
| 23 | if (server) { | ||
| 24 | std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler; | ||
| 25 | if (hle_handler) | ||
| 26 | hle_handler->ClientDisconnected(server); | ||
| 22 | 27 | ||
| 23 | // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set | 28 | // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set |
| 24 | // their WaitSynchronization result to 0xC920181A. | 29 | // their WaitSynchronization result to 0xC920181A. |
| @@ -28,11 +33,13 @@ ClientSession::~ClientSession() { | |||
| 28 | } | 33 | } |
| 29 | 34 | ||
| 30 | ResultCode ClientSession::SendSyncRequest() { | 35 | ResultCode ClientSession::SendSyncRequest() { |
| 31 | // Signal the server session that new data is available | 36 | // Keep ServerSession alive until we're done working with it. |
| 32 | if (parent->server) | 37 | SharedPtr<ServerSession> server = parent->server; |
| 33 | return parent->server->HandleSyncRequest(); | 38 | if (server == nullptr) |
| 39 | return ERR_SESSION_CLOSED_BY_REMOTE; | ||
| 34 | 40 | ||
| 35 | return ERR_SESSION_CLOSED_BY_REMOTE; | 41 | // Signal the server session that new data is available |
| 42 | return server->HandleSyncRequest(); | ||
| 36 | } | 43 | } |
| 37 | 44 | ||
| 38 | } // namespace | 45 | } // namespace |
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 28f365b9e..5365605da 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/kernel/session.h" | ||
| 13 | #include "core/hle/kernel/wait_object.h" | 12 | #include "core/hle/kernel/wait_object.h" |
| 14 | #include "core/hle/result.h" | 13 | #include "core/hle/result.h" |
| 15 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| @@ -19,6 +18,7 @@ namespace Kernel { | |||
| 19 | class ClientSession; | 18 | class ClientSession; |
| 20 | class ClientPort; | 19 | class ClientPort; |
| 21 | class ServerSession; | 20 | class ServerSession; |
| 21 | class Session; | ||
| 22 | class SessionRequestHandler; | 22 | class SessionRequestHandler; |
| 23 | class Thread; | 23 | class Thread; |
| 24 | 24 | ||
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 084113188..6c4600f25 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp | |||
| @@ -423,6 +423,102 @@ static void SetApplicationData(Interface* self) { | |||
| 423 | rb.Push(RESULT_SUCCESS); | 423 | rb.Push(RESULT_SUCCESS); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | /** | ||
| 427 | * NWM_UDS::DecryptBeaconData service function. | ||
| 428 | * Decrypts the encrypted data tags contained in the 802.11 beacons. | ||
| 429 | * Inputs: | ||
| 430 | * 1 : Input network struct buffer descriptor. | ||
| 431 | * 2 : Input network struct buffer ptr. | ||
| 432 | * 3 : Input tag0 encrypted buffer descriptor. | ||
| 433 | * 4 : Input tag0 encrypted buffer ptr. | ||
| 434 | * 5 : Input tag1 encrypted buffer descriptor. | ||
| 435 | * 6 : Input tag1 encrypted buffer ptr. | ||
| 436 | * 64 : Output buffer descriptor. | ||
| 437 | * 65 : Output buffer ptr. | ||
| 438 | * Outputs: | ||
| 439 | * 0 : Return header | ||
| 440 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 441 | */ | ||
| 442 | static void DecryptBeaconData(Interface* self) { | ||
| 443 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 0, 6); | ||
| 444 | |||
| 445 | size_t desc_size; | ||
| 446 | const VAddr network_struct_addr = rp.PopStaticBuffer(&desc_size); | ||
| 447 | ASSERT(desc_size == sizeof(NetworkInfo)); | ||
| 448 | |||
| 449 | size_t data0_size; | ||
| 450 | const VAddr encrypted_data0_addr = rp.PopStaticBuffer(&data0_size); | ||
| 451 | |||
| 452 | size_t data1_size; | ||
| 453 | const VAddr encrypted_data1_addr = rp.PopStaticBuffer(&data1_size); | ||
| 454 | |||
| 455 | size_t output_buffer_size; | ||
| 456 | const VAddr output_buffer_addr = rp.PeekStaticBuffer(0, &output_buffer_size); | ||
| 457 | |||
| 458 | // This size is hardcoded in the 3DS UDS code. | ||
| 459 | ASSERT(output_buffer_size == sizeof(NodeInfo) * UDSMaxNodes); | ||
| 460 | |||
| 461 | LOG_WARNING(Service_NWM, "called in0=%08X in1=%08X out=%08X", encrypted_data0_addr, | ||
| 462 | encrypted_data1_addr, output_buffer_addr); | ||
| 463 | |||
| 464 | NetworkInfo net_info; | ||
| 465 | Memory::ReadBlock(network_struct_addr, &net_info, sizeof(net_info)); | ||
| 466 | |||
| 467 | // Read the encrypted data. | ||
| 468 | // The first 4 bytes should be the OUI and the OUI Type of the tags. | ||
| 469 | std::array<u8, 3> oui; | ||
| 470 | Memory::ReadBlock(encrypted_data0_addr, oui.data(), oui.size()); | ||
| 471 | ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI"); | ||
| 472 | Memory::ReadBlock(encrypted_data1_addr, oui.data(), oui.size()); | ||
| 473 | ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI"); | ||
| 474 | |||
| 475 | ASSERT_MSG(Memory::Read8(encrypted_data0_addr + 3) == | ||
| 476 | static_cast<u8>(NintendoTagId::EncryptedData0), | ||
| 477 | "Unexpected tag id"); | ||
| 478 | ASSERT_MSG(Memory::Read8(encrypted_data1_addr + 3) == | ||
| 479 | static_cast<u8>(NintendoTagId::EncryptedData1), | ||
| 480 | "Unexpected tag id"); | ||
| 481 | |||
| 482 | std::vector<u8> beacon_data(data0_size + data1_size); | ||
| 483 | Memory::ReadBlock(encrypted_data0_addr + 4, beacon_data.data(), data0_size); | ||
| 484 | Memory::ReadBlock(encrypted_data1_addr + 4, beacon_data.data() + data0_size, data1_size); | ||
| 485 | |||
| 486 | // Decrypt the data | ||
| 487 | DecryptBeaconData(net_info, beacon_data); | ||
| 488 | |||
| 489 | // The beacon data header contains the MD5 hash of the data. | ||
| 490 | BeaconData beacon_header; | ||
| 491 | std::memcpy(&beacon_header, beacon_data.data(), sizeof(beacon_header)); | ||
| 492 | |||
| 493 | // TODO(Subv): Verify the MD5 hash of the data and return 0xE1211005 if invalid. | ||
| 494 | |||
| 495 | u8 num_nodes = net_info.max_nodes; | ||
| 496 | |||
| 497 | std::vector<NodeInfo> nodes; | ||
| 498 | |||
| 499 | for (int i = 0; i < num_nodes; ++i) { | ||
| 500 | BeaconNodeInfo info; | ||
| 501 | std::memcpy(&info, beacon_data.data() + sizeof(beacon_header) + i * sizeof(info), | ||
| 502 | sizeof(info)); | ||
| 503 | |||
| 504 | // Deserialize the node information. | ||
| 505 | NodeInfo node{}; | ||
| 506 | node.friend_code_seed = info.friend_code_seed; | ||
| 507 | node.network_node_id = info.network_node_id; | ||
| 508 | for (int i = 0; i < info.username.size(); ++i) | ||
| 509 | node.username[i] = info.username[i]; | ||
| 510 | |||
| 511 | nodes.push_back(node); | ||
| 512 | } | ||
| 513 | |||
| 514 | Memory::ZeroBlock(output_buffer_addr, sizeof(NodeInfo) * UDSMaxNodes); | ||
| 515 | Memory::WriteBlock(output_buffer_addr, nodes.data(), sizeof(NodeInfo) * nodes.size()); | ||
| 516 | |||
| 517 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||
| 518 | rb.PushStaticBuffer(output_buffer_addr, output_buffer_size, 0); | ||
| 519 | rb.Push(RESULT_SUCCESS); | ||
| 520 | } | ||
| 521 | |||
| 426 | // Sends a 802.11 beacon frame with information about the current network. | 522 | // Sends a 802.11 beacon frame with information about the current network. |
| 427 | static void BeaconBroadcastCallback(u64 userdata, int cycles_late) { | 523 | static void BeaconBroadcastCallback(u64 userdata, int cycles_late) { |
| 428 | // Don't do anything if we're not actually hosting a network | 524 | // Don't do anything if we're not actually hosting a network |
| @@ -463,7 +559,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 463 | {0x001B0302, InitializeWithVersion, "InitializeWithVersion"}, | 559 | {0x001B0302, InitializeWithVersion, "InitializeWithVersion"}, |
| 464 | {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"}, | 560 | {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"}, |
| 465 | {0x001E0084, nullptr, "ConnectToNetwork"}, | 561 | {0x001E0084, nullptr, "ConnectToNetwork"}, |
| 466 | {0x001F0006, nullptr, "DecryptBeaconData"}, | 562 | {0x001F0006, DecryptBeaconData, "DecryptBeaconData"}, |
| 467 | {0x00200040, nullptr, "Flush"}, | 563 | {0x00200040, nullptr, "Flush"}, |
| 468 | {0x00210080, nullptr, "SetProbeResponseParam"}, | 564 | {0x00210080, nullptr, "SetProbeResponseParam"}, |
| 469 | {0x00220402, nullptr, "ScanOnConnection"}, | 565 | {0x00220402, nullptr, "ScanOnConnection"}, |