2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
22 * @brief Implementation of class for managing one container
27 #include "container.hpp"
29 #include "log/logger.hpp"
30 #include "utils/paths.hpp"
31 #include "config/manager.hpp"
33 #include <boost/filesystem.hpp>
39 namespace security_containers {
41 namespace fs = boost::filesystem;
45 typedef std::lock_guard<std::recursive_mutex> Lock;
47 // TODO: move constants to the config file when default values are implemented there
48 const int RECONNECT_RETRIES = 15;
49 const int RECONNECT_DELAY = 1 * 1000;
53 Container::Container(const std::string& containerConfigPath,
54 const std::string& baseRunMountPointPath)
56 config::loadFromFile(containerConfigPath, mConfig);
58 for (std::string r: mConfig.permittedToSend) {
59 mPermittedToSend.push_back(boost::regex(r));
61 for (std::string r: mConfig.permittedToRecv) {
62 mPermittedToRecv.push_back(boost::regex(r));
65 const std::string baseConfigPath = utils::dirName(containerConfigPath);
66 mConfig.config = fs::absolute(mConfig.config, baseConfigPath).string();
67 mConfig.networkConfig = fs::absolute(mConfig.networkConfig, baseConfigPath).string();
68 if (!mConfig.runMountPoint.empty()) {
69 mRunMountPoint = fs::absolute(mConfig.runMountPoint, baseRunMountPointPath).string();
72 LOGT("Creating Network Admin " << mConfig.networkConfig);
73 mNetworkAdmin.reset(new NetworkAdmin(mConfig));
74 LOGT("Creating Container Admin " << mConfig.config);
75 mAdmin.reset(new ContainerAdmin(mConfig));
78 Container::~Container()
80 // Make sure all OnNameLostCallbacks get finished and no new will
81 // get called before proceeding further. This guarantees no race
82 // condition on the mReconnectThread.
84 Lock lock(mReconnectMutex);
88 if (mReconnectThread.joinable()) {
89 mReconnectThread.join();
93 const std::vector<boost::regex>& Container::getPermittedToSend() const
95 return mPermittedToSend;
98 const std::vector<boost::regex>& Container::getPermittedToRecv() const
100 return mPermittedToRecv;
103 const std::string& Container::getId() const
105 Lock lock(mReconnectMutex);
106 return mAdmin->getId();
109 int Container::getPrivilege() const
111 return mConfig.privilege;
114 void Container::start()
116 Lock lock(mReconnectMutex);
117 mConnectionTransport.reset(new ContainerConnectionTransport(mRunMountPoint));
118 mNetworkAdmin->start();
120 mConnection.reset(new ContainerConnection(mConnectionTransport->acquireAddress(),
121 std::bind(&Container::onNameLostCallback, this)));
122 if (mNotifyCallback) {
123 mConnection->setNotifyActiveContainerCallback(mNotifyCallback);
125 if (mDisplayOffCallback) {
126 mConnection->setDisplayOffCallback(mDisplayOffCallback);
128 if (mFileMoveCallback) {
129 mConnection->setFileMoveRequestCallback(mFileMoveCallback);
132 // Send to the background only after we're connected,
133 // otherwise it'd take ages.
134 LOGD(getId() << ": DBUS connected, sending to the background");
138 void Container::stop()
140 Lock lock(mReconnectMutex);
143 mNetworkAdmin->stop();
144 mConnectionTransport.reset();
147 void Container::goForeground()
149 Lock lock(mReconnectMutex);
150 mAdmin->setSchedulerLevel(SchedulerLevel::FOREGROUND);
153 void Container::goBackground()
155 Lock lock(mReconnectMutex);
156 mAdmin->setSchedulerLevel(SchedulerLevel::BACKGROUND);
159 void Container::setDetachOnExit()
161 Lock lock(mReconnectMutex);
162 mNetworkAdmin->setDetachOnExit();
163 mAdmin->setDetachOnExit();
164 mConnectionTransport->setDetachOnExit();
167 bool Container::isRunning()
169 Lock lock(mReconnectMutex);
170 return mAdmin->isRunning();
173 bool Container::isStopped()
175 Lock lock(mReconnectMutex);
176 return mAdmin->isStopped();
179 bool Container::isPaused()
181 Lock lock(mReconnectMutex);
182 return mAdmin->isPaused();
185 void Container::onNameLostCallback()
187 LOGI(getId() << ": A connection to the DBUS server has been lost, reconnecting...");
189 if (mReconnectThread.joinable()) {
190 mReconnectThread.join();
192 mReconnectThread = std::thread(std::bind(&Container::reconnectHandler, this));
195 void Container::reconnectHandler()
198 Lock lock(mReconnectMutex);
202 for (int i = 0; i < RECONNECT_RETRIES; ++i) {
203 // This sleeps even before the first try to give DBUS some time to come back up
204 std::this_thread::sleep_for(std::chrono::milliseconds(RECONNECT_DELAY));
206 Lock lock(mReconnectMutex);
208 LOGI(getId() << ": Has stopped, nothing to reconnect to, bailing out");
213 LOGT(getId() << ": Reconnect try " << i + 1);
214 mConnection.reset(new ContainerConnection(mConnectionTransport->acquireAddress(),
215 std::bind(&Container::onNameLostCallback, this)));
216 LOGI(getId() << ": Reconnected");
218 } catch (SecurityContainersException&) {
219 LOGT(getId() << ": Reconnect try " << i + 1 << " has been unsuccessful");
223 LOGE(getId() << ": Reconnecting to the DBUS has failed, stopping the container");
227 void Container::setNotifyActiveContainerCallback(const NotifyActiveContainerCallback& callback)
229 Lock lock(mReconnectMutex);
230 mNotifyCallback = callback;
232 mConnection->setNotifyActiveContainerCallback(mNotifyCallback);
236 void Container::sendNotification(const std::string& container,
237 const std::string& application,
238 const std::string& message)
240 Lock lock(mReconnectMutex);
242 mConnection->sendNotification(container, application, message);
244 LOGE(getId() << ": Can't send notification, no connection to DBUS");
248 void Container::setDisplayOffCallback(const DisplayOffCallback& callback)
250 Lock lock(mReconnectMutex);
252 mDisplayOffCallback = callback;
254 mConnection->setDisplayOffCallback(callback);
258 void Container::setFileMoveRequestCallback(const FileMoveRequestCallback& callback)
260 Lock lock(mReconnectMutex);
262 mFileMoveCallback = callback;
264 mConnection->setFileMoveRequestCallback(callback);
269 } // namespace security_containers