Add API to create new containers
[platform/core/security/vasum.git] / server / host-connection.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
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 /**
20  * @file
21  * @author  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
22  * @brief   Implementation of a class for communication with server
23  */
24
25 #include "config.hpp"
26
27 #include "host-connection.hpp"
28 #include "host-dbus-definitions.hpp"
29 #include "exception.hpp"
30
31 #include "logger/logger.hpp"
32
33
34 namespace security_containers {
35
36 namespace {
37
38 // Timeout in ms for waiting for dbus name.
39 // Can happen if glib loop is busy or not present.
40 // TODO: this should be in host's configuration file
41 const unsigned int NAME_ACQUIRED_TIMEOUT = 5 * 1000;
42
43 } // namespace
44
45
46 HostConnection::HostConnection()
47     : mNameAcquired(false)
48     , mNameLost(false)
49 {
50     LOGT("Connecting to host system DBUS");
51     mDbusConnection = dbus::DbusConnection::createSystem();
52
53     LOGT("Setting DBUS name");
54     mDbusConnection->setName(api::host::BUS_NAME,
55                              std::bind(&HostConnection::onNameAcquired, this),
56                              std::bind(&HostConnection::onNameLost, this));
57
58     if (!waitForName(NAME_ACQUIRED_TIMEOUT)) {
59         LOGE("Could not acquire dbus name: " << api::host::BUS_NAME);
60         throw HostConnectionException("Could not acquire dbus name: " + api::host::BUS_NAME);
61     }
62
63     LOGT("Registering DBUS interface");
64     using namespace std::placeholders;
65     mDbusConnection->registerObject(api::host::OBJECT_PATH,
66                                     api::host::DEFINITION,
67                                     std::bind(&HostConnection::onMessageCall,
68                                               this, _1, _2, _3, _4, _5));
69
70     LOGD("Connected");
71 }
72
73 HostConnection::~HostConnection()
74 {
75 }
76
77 bool HostConnection::waitForName(const unsigned int timeoutMs)
78 {
79     std::unique_lock<std::mutex> lock(mNameMutex);
80     mNameCondition.wait_for(lock,
81                             std::chrono::milliseconds(timeoutMs),
82                             [this] {
83                                 return mNameAcquired || mNameLost;
84                             });
85
86     return mNameAcquired;
87 }
88
89 void HostConnection::onNameAcquired()
90 {
91     std::unique_lock<std::mutex> lock(mNameMutex);
92     mNameAcquired = true;
93     mNameCondition.notify_one();
94 }
95
96 void HostConnection::onNameLost()
97 {
98     std::unique_lock<std::mutex> lock(mNameMutex);
99     mNameLost = true;
100     mNameCondition.notify_one();
101
102     if (mNameAcquired) {
103         // TODO implement reconnecting
104         LOGE("TODO Reconnect !!!");
105     }
106 }
107
108 void HostConnection::setProxyCallCallback(const ProxyCallCallback& callback)
109 {
110     mProxyCallCallback = callback;
111 }
112
113 void HostConnection::setGetContainerDbusesCallback(const GetContainerDbusesCallback& callback)
114 {
115     mGetContainerDbusesCallback = callback;
116 }
117
118 void HostConnection::setGetContainerIdsCallback(const GetContainerIdsCallback& callback)
119 {
120     mGetContainerIdsCallback = callback;
121 }
122
123 void HostConnection::setGetActiveContainerIdCallback(const GetActiveContainerIdCallback& callback)
124 {
125     mGetActiveContainerIdCallback = callback;
126 }
127
128 void HostConnection::setSetActiveContainerCallback(const SetActiveContainerCallback& callback)
129 {
130     mSetActiveContainerCallback = callback;
131 }
132
133 void HostConnection::setAddContainerCallback(const AddContainerCallback& callback)
134 {
135     mAddContainerCallback = callback;
136 }
137
138 void HostConnection::onMessageCall(const std::string& objectPath,
139                                         const std::string& interface,
140                                         const std::string& methodName,
141                                         GVariant* parameters,
142                                         dbus::MethodResultBuilder::Pointer result)
143 {
144     if (objectPath != api::host::OBJECT_PATH || interface != api::host::INTERFACE) {
145         return;
146     }
147
148     if (methodName == api::host::METHOD_SET_ACTIVE_CONTAINER) {
149         const gchar* id = NULL;
150         g_variant_get(parameters, "(&s)", &id);
151
152         if (mSetActiveContainerCallback) {
153             mSetActiveContainerCallback(id, result);
154         }
155         return;
156     }
157
158     if (methodName == api::host::METHOD_GET_CONTAINER_DBUSES) {
159         if (mGetContainerDbusesCallback) {
160             mGetContainerDbusesCallback(result);
161         }
162         return;
163     }
164
165     if (methodName == api::METHOD_PROXY_CALL) {
166         const gchar* target = NULL;
167         const gchar* targetBusName = NULL;
168         const gchar* targetObjectPath = NULL;
169         const gchar* targetInterface = NULL;
170         const gchar* targetMethod = NULL;
171         GVariant* rawArgs = NULL;
172         g_variant_get(parameters,
173                       "(&s&s&s&s&sv)",
174                       &target,
175                       &targetBusName,
176                       &targetObjectPath,
177                       &targetInterface,
178                       &targetMethod,
179                       &rawArgs);
180         dbus::GVariantPtr args(rawArgs, g_variant_unref);
181
182         if (mProxyCallCallback) {
183             mProxyCallCallback(target,
184                                targetBusName,
185                                targetObjectPath,
186                                targetInterface,
187                                targetMethod,
188                                args.get(),
189                                result);
190         }
191         return;
192     }
193
194     if (methodName == api::host::METHOD_GET_CONTAINER_ID_LIST){
195         if (mGetContainerIdsCallback){
196             mGetContainerIdsCallback(result);
197         }
198         return;
199     }
200
201     if (methodName == api::host::METHOD_GET_ACTIVE_CONTAINER_ID){
202         if (mGetActiveContainerIdCallback){
203             mGetActiveContainerIdCallback(result);
204         }
205         return;
206     }
207
208     if (methodName == api::host::METHOD_ADD_CONTAINER) {
209         const gchar* id = NULL;
210         g_variant_get(parameters, "(&s)", &id);
211
212         if (mAddContainerCallback){
213             mAddContainerCallback(id, result);
214         }
215     }
216 }
217
218 void HostConnection::proxyCallAsync(const std::string& busName,
219                                     const std::string& objectPath,
220                                     const std::string& interface,
221                                     const std::string& method,
222                                     GVariant* parameters,
223                                     const dbus::DbusConnection::AsyncMethodCallCallback& callback)
224 {
225     mDbusConnection->callMethodAsync(busName,
226                                      objectPath,
227                                      interface,
228                                      method,
229                                      parameters,
230                                      std::string(),
231                                      callback);
232 }
233
234 void HostConnection::signalContainerDbusState(const std::string& containerId,
235                                               const std::string& dbusAddress)
236 {
237     GVariant* parameters = g_variant_new("(ss)", containerId.c_str(), dbusAddress.c_str());
238     mDbusConnection->emitSignal(api::host::OBJECT_PATH,
239                                 api::host::INTERFACE,
240                                 api::host::SIGNAL_CONTAINER_DBUS_STATE,
241                                 parameters);
242 }
243
244
245 } // namespace security_containers