Commit summary:
[platform/core/security/suspicious-activity-monitor.git] / daemon / dbus / dbuslistener.cpp
1 /**
2  * Samsung Ukraine R&D Center (SRK under a contract between)
3  * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
4  * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License
17  */
18 /**
19  * @file   dbuslistener.cpp
20  * @brief  DBusListener class source
21  * @date   Created Aug 21, 2018
22  * @author Mail to: <A HREF="mailto:i.metelytsia@samsung.com">Iurii Metelytsia, i.metelytsia@samsung.com</A>
23  */
24
25 #include <thread>
26 #include <stdexcept>
27 #include <jsoncpp/json/reader.h>
28
29 #include "samonitor_tag.h"
30 #include "logging.h"
31 #include "dbuslistener.h"
32 #include "dbushandler.h"
33
34 namespace dbus
35 {
36
37 DBusMessageHelper::DBusMessageHelper(DBusMessage* message) : m_message(message), m_message_ptr(nullptr)
38 {
39     if (!m_message) {
40         throw std::runtime_error("Empty DBUS message");
41     }
42
43     if (dbus_message_is_signal(m_message, "com.samsung.sam.interface", "Control")) {
44         DBusMessageIter args;
45         if (dbus_message_iter_init(m_message, &args) && (dbus_message_iter_get_arg_type(&args) == DBUS_TYPE_STRING)) {
46             dbus_message_iter_get_basic(&args, &m_message_ptr);
47         }
48     }
49 }
50
51 DBusMessageHelper::~DBusMessageHelper()
52 {
53     dbus_message_unref(m_message);
54 }
55
56 DBusListener::DBusListener(AllowedPredicate&& allowed) : m_connection(nullptr), m_predicate(allowed), m_handlers(), m_mutex()
57 {
58     if ((m_connection = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr)) == nullptr) {
59         LOG_E(TAG, "dbus_bus_get failed!");
60         throw std::runtime_error("dbus_bus_get failed!");
61     }
62
63     if (dbus_bus_request_name(m_connection, "com.samsung.sam.sink", DBUS_NAME_FLAG_REPLACE_EXISTING , nullptr) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
64         LOG_E(TAG, "dbus_bus_request_name failed!");
65         dbus_connection_unref(m_connection);
66         throw std::runtime_error("dbus_bus_request_name failed!");
67     }
68
69     dbus_bus_add_match(m_connection, "type='signal',interface='com.samsung.sam.interface'", nullptr);
70     dbus_connection_flush(m_connection);
71 }
72
73 DBusListener::~DBusListener()
74 {
75     dbus_connection_unref(m_connection);
76 }
77
78 bool DBusListener::addHandler(const std::string& type, DBusHandler* handler)
79 {
80     std::lock_guard<std::mutex> lock(m_mutex);
81     return (m_handlers.insert(std::make_pair(type, handler)).second == true);
82 }
83
84 void DBusListener::removeHandler(const std::string& type)
85 {
86     std::lock_guard<std::mutex> lock(m_mutex);
87     m_handlers.erase(type);
88 }
89
90 void DBusListener::loop()
91 {
92     while (isAllowed()) {
93         try {
94             dbus_connection_read_write(m_connection, 0);
95
96             DBusMessage* message = dbus_connection_pop_message(m_connection);
97             if (message == nullptr) {
98                 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
99                 continue;
100             }
101
102             DBusMessageHelper helper(message);
103             const char* message_ptr = helper.message();
104
105             if (message_ptr) {
106                 LOG_D(TAG, "DBUS message received: %.256s", message_ptr);
107
108                 Json::Reader reader;
109                 Json::Value value;
110
111                 if (reader.parse(message_ptr, value)) {
112                     std::lock_guard<std::mutex> lock(m_mutex);
113                     auto it = m_handlers.find(value["type"].asString());
114                     if (it != m_handlers.end()) {
115                         it->second->process(value["data"]);
116                     } else {
117                         LOG_E(TAG, "Unknown type");
118                     }
119                 } else {
120                     LOG_E(TAG, "Incorrect JSON");
121                 }
122             }
123         } catch (std::exception& e) {
124             LOG_E(TAG, "DBusListener loop exception: %s", e.what());
125         }
126     }
127 }
128
129 } // namespace dbus