From e17c0019c5cf9faaa8f23e3904342c8c4faf0980 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Thu, 28 Dec 2017 23:30:21 -0500
Subject: [PATCH] kernel: Add basic support for Domain object.

---
 src/core/CMakeLists.txt           |  2 ++
 src/core/hle/kernel/domain.cpp    | 44 ++++++++++++++++++++++++++++++
 src/core/hle/kernel/domain.h      | 45 +++++++++++++++++++++++++++++++
 src/core/hle/kernel/kernel.h      | 17 ++++++++++++
 src/core/hle/kernel/sync_object.h |  8 +++---
 5 files changed, 112 insertions(+), 4 deletions(-)
 create mode 100644 src/core/hle/kernel/domain.cpp
 create mode 100644 src/core/hle/kernel/domain.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 29abb703f0..1e023303d3 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -29,6 +29,7 @@ set(SRCS
             hle/kernel/address_arbiter.cpp
             hle/kernel/client_port.cpp
             hle/kernel/client_session.cpp
+            hle/kernel/domain.cpp
             hle/kernel/event.cpp
             hle/kernel/handle_table.cpp
             hle/kernel/hle_ipc.cpp
@@ -118,6 +119,7 @@ set(HEADERS
             hle/kernel/address_arbiter.h
             hle/kernel/client_port.h
             hle/kernel/client_session.h
+            hle/kernel/domain.h
             hle/kernel/errors.h
             hle/kernel/event.h
             hle/kernel/handle_table.h
diff --git a/src/core/hle/kernel/domain.cpp b/src/core/hle/kernel/domain.cpp
new file mode 100644
index 0000000000..19ba861f5a
--- /dev/null
+++ b/src/core/hle/kernel/domain.cpp
@@ -0,0 +1,44 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/domain.h"
+#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/session.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+ResultVal<SharedPtr<Domain>> Domain::Create(std::string name) {
+    SharedPtr<Domain> domain(new Domain);
+    domain->name = std::move(name);
+    return MakeResult(std::move(domain));
+}
+
+ResultVal<SharedPtr<Domain>> Domain::CreateFromSession(const Session& session) {
+    auto res = Create(session.port->GetName() + "_Domain");
+    auto& domain = res.Unwrap();
+    domain->request_handlers.push_back(std::move(session.server->hle_handler));
+    Kernel::g_handle_table.ConvertSessionToDomain(session, domain);
+    return res;
+}
+
+ResultCode Domain::SendSyncRequest(SharedPtr<Thread> thread) {
+    Kernel::HLERequestContext context(this);
+    u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress());
+    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
+                                              Kernel::g_handle_table);
+
+    auto& domain_message_header = context.GetDomainMessageHeader();
+    if (domain_message_header) {
+        // If there is a DomainMessageHeader, then this is CommandType "Request"
+        const u32 object_id{context.GetDomainMessageHeader()->object_id};
+        return request_handlers[object_id - 1]->HandleSyncRequest(context);
+    }
+    return request_handlers.front()->HandleSyncRequest(context);
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/domain.h b/src/core/hle/kernel/domain.h
new file mode 100644
index 0000000000..74f7ad0dd4
--- /dev/null
+++ b/src/core/hle/kernel/domain.h
@@ -0,0 +1,45 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+#include "core/hle/kernel/sync_object.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class Session;
+class SessionRequestHandler;
+
+class Domain final : public SyncObject {
+public:
+    std::string GetTypeName() const override {
+        return "Domain";
+    }
+
+    static const HandleType HANDLE_TYPE = HandleType::Domain;
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+    static ResultVal<SharedPtr<Domain>> CreateFromSession(const Session& server);
+
+    ResultCode SendSyncRequest(SharedPtr<Thread> thread) override;
+
+    /// The name of this domain (optional)
+    std::string name;
+
+    std::vector<std::shared_ptr<SessionRequestHandler>> request_handlers;
+
+private:
+    Domain() = default;
+    ~Domain() override = default;
+
+    static ResultVal<SharedPtr<Domain>> Create(std::string name = "Unknown");
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 73fab3981e..e43055bfdd 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -31,6 +31,7 @@ enum class HandleType : u32 {
     ServerPort,
     ClientSession,
     ServerSession,
+    Domain,
 };
 
 enum {
@@ -83,12 +84,28 @@ public:
         case HandleType::CodeSet:
         case HandleType::ClientPort:
         case HandleType::ClientSession:
+        case HandleType::Domain:
             return false;
         }
 
         UNREACHABLE();
     }
 
+    /**
+     * Check if svcSendSyncRequest can be called on the object
+     * @return True svcSendSyncRequest can be called on the object, otherwise false
+     */
+    bool IsSyncable() const {
+        switch (GetHandleType()) {
+        case HandleType::ClientSession:
+        case HandleType::Domain:
+            return true;
+        }
+
+        UNREACHABLE();
+    }
+
+
 public:
     static unsigned int next_object_id;
 
diff --git a/src/core/hle/kernel/sync_object.h b/src/core/hle/kernel/sync_object.h
index ce2835ca4b..5d715226e0 100644
--- a/src/core/hle/kernel/sync_object.h
+++ b/src/core/hle/kernel/sync_object.h
@@ -16,10 +16,10 @@ class Thread;
 class SyncObject : public Object {
 public:
     /**
-    * Handle a sync request from the emulated application.
-    * @param thread Thread that initiated the request.
-    * @returns ResultCode from the operation.
-    */
+     * Handle a sync request from the emulated application.
+     * @param thread Thread that initiated the request.
+     * @returns ResultCode from the operation.
+     */
     virtual ResultCode SendSyncRequest(SharedPtr<Thread> thread) = 0;
 };
 
-- 
GitLab