summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/citra_qt/debugger/wait_tree.h1
-rw-r--r--src/core/hle/kernel/client_session.cpp21
-rw-r--r--src/core/hle/kernel/server_session.h2
-rw-r--r--src/core/hle/service/nwm/nwm_uds.cpp98
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;
18class Event; 18class Event;
19class Mutex; 19class Mutex;
20class Semaphore; 20class Semaphore;
21class Session;
22class Thread; 21class Thread;
23class Timer; 22class 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
12namespace Kernel { 13namespace 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
30ResultCode ClientSession::SendSyncRequest() { 35ResultCode 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 {
19class ClientSession; 18class ClientSession;
20class ClientPort; 19class ClientPort;
21class ServerSession; 20class ServerSession;
21class Session;
22class SessionRequestHandler; 22class SessionRequestHandler;
23class Thread; 23class 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 */
442static 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.
427static void BeaconBroadcastCallback(u64 userdata, int cycles_late) { 523static 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"},