});
}
-VsmStatus Client::vsm_notify_active_zone(const char* /*application*/, const char* /*message*/) noexcept
-{
- return coverException([&] {
- //TODO: Implement vsm_notify_active_zone
- throw OperationFailedException("Not implemented");
- });
-}
-
-VsmStatus Client::vsm_file_move_request(const char* /*destZone*/, const char* /*path*/) noexcept
-{
- return coverException([&] {
- //TODO: Implement vsm_file_move_request
- throw OperationFailedException("Not implemented");
- });
-}
-
-VsmStatus Client::vsm_add_notification_callback(VsmNotificationFunction /*notificationCallback*/,
- void* /*data*/,
- VsmSubscriptionId* /*subscriptionId*/) noexcept
-{
- return coverException([&] {
- //TODO: Implement vsm_add_notification_callback
- throw OperationFailedException("Not implemented");
- });
-}
-
-VsmStatus Client::vsm_del_notification_callback(VsmSubscriptionId subscriptionId) noexcept
-{
- return coverException([&] {
- mClient->removeMethod(subscriptionId);
- });
-}
-
typedef std::function<void (const char *zoneId, const char *dbusAddress, void *data)> VsmZoneDbusStateFunction;
/**
- * Notification callback function signature.
- *
- * @param[in] zone source zone
- * @param[in] application sending application name
- * @param[in] message notification message
- * @param data custom user's data pointer passed to vsm_add_notification_callback()
- */
-typedef std::function<void(const char *zone, const char *application, const char *message, void *data)>
- VsmNotificationFunction;
-
-/**
* vasum's client definition.
*
* Client uses dbus API.
*/
VsmStatus vsm_remove_declaration(const char* zone, VsmString declaration) noexcept;
- /**
- * @see ::vsm_notify_active_zone
- */
- VsmStatus vsm_notify_active_zone(const char* application, const char* message) noexcept;
-
- /**
- * @see ::vsm_file_move_request
- */
- VsmStatus vsm_file_move_request(const char* destZone, const char* path) noexcept;
-
- /**
- * @see ::vsm_add_notification_callback
- */
- VsmStatus vsm_add_notification_callback(VsmNotificationFunction notificationCallback,
- void* data,
- VsmSubscriptionId* subscriptionId) noexcept;
-
- /**
- * @see ::vsm_del_notification_callback
- */
- VsmStatus vsm_del_notification_callback(VsmSubscriptionId subscriptionId) noexcept;
-
private:
struct Status {
Status();
return getClient(client).vsm_remove_declaration(zone, declaration);
}
-API VsmStatus vsm_notify_active_zone(VsmClient client,
- const char* application,
- const char* message)
-{
- return getClient(client).vsm_notify_active_zone(application, message);
-}
-
-API VsmStatus vsm_file_move_request(VsmClient client, const char* destZone, const char* path)
-{
- return getClient(client).vsm_file_move_request(destZone, path);
-}
-
-API VsmStatus vsm_add_notification_callback(VsmClient client,
- VsmNotificationCallback notificationCallback,
- void* data,
- VsmSubscriptionId* subscriptionId)
-{
- return getClient(client).vsm_add_notification_callback(notificationCallback, data, subscriptionId);
-}
-
-API VsmStatus vsm_del_notification_callback(VsmClient client,
- VsmSubscriptionId subscriptionId)
-{
- return getClient(client).vsm_del_notification_callback(subscriptionId);
-}
-
/** @} Host API */
-/**
- * @name Zone API
- *
- * Functions using org.tizen.vasum.zone.manager D-Bus interface.
- *
- * @{
- */
-
-/**
- * Notification callback function signature.
- *
- * @param[in] zone source zone
- * @param[in] application sending application name
- * @param[in] message notification message
- * @param data custom user's data pointer passed to vsm_add_notification_callback()
- */
-typedef void (*VsmNotificationCallback)(const char* zone,
- const char* application,
- const char* message,
- void* data);
-/**
- * Send message to active zone.
- *
- * @param[in] client vasum-server's client
- * @param[in] application application name
- * @param[in] message message
- * @return status of this function call
- */
-VsmStatus vsm_notify_active_zone(VsmClient client, const char* application, const char* message);
-
-/**
- * Move file between zones.
- *
- * @param[in] client vasum-server's client
- * @param[in] destZone destination zone id
- * @param[in] path path to moved file
- * @return status of this function call
- */
-VsmStatus vsm_file_move_request(VsmClient client, const char* destZone, const char* path);
-
-/**
- * Register notification callback function.
- *
- * @note The callback function will be invoked on a different thread.
- *
- * @param[in] client vasum-server's client
- * @param[in] notificationCallback callback function
- * @param[in] data some extra data that will be passed to callback function
- * @param[out] subscriptionId subscription identifier that can be used to unsubscribe signal,
- * pointer can be NULL.
- * @return status of this function call
- */
-VsmStatus vsm_add_notification_callback(VsmClient client,
- VsmNotificationCallback notificationCallback,
- void* data,
- VsmSubscriptionId* subscriptionId);
-
-/**
- * Unregister notification callback function.
- *
- * @param[in] client vasum-server's client
- * @param[in] subscriptionId subscription identifier returned by vsm_add_notification_callback
- * @return status of this function call
- */
-VsmStatus vsm_del_notification_callback(VsmClient client, VsmSubscriptionId subscriptionId);
-
#endif /* __VASUM_WRAPPER_SOURCE__ */
-/** @} Zone API */
-
#ifdef __cplusplus
}
#endif
typedef api::String ZoneId;
typedef api::String Declaration;
-typedef api::String FileMoveRequestStatus;
typedef api::StringPair GetNetDevAttrsIn;
typedef api::StringPair CreateNetDevPhysIn;
typedef api::StringPair RemoveDeclarationIn;
typedef api::StringPair RevokeDeviceIn;
typedef api::StringPair DestroyNetDevIn;
typedef api::StringPair ConnectionState;
-typedef api::StringPair NotifActiveZoneIn;
-typedef api::StringPair FileMoveRequestIn;
typedef api::VectorOfStrings ZoneIds;
typedef api::VectorOfStrings Declarations;
typedef api::VectorOfStrings NetDevList;
)
};
-struct Notification {
- std::string zone;
- std::string application;
- std::string message;
-
- CONFIG_REGISTER
- (
- zone,
- application,
- message
- )
-};
-
} // namespace api
} // namespace vasum
"switchToDefaultAfterTimeout" : true,
"runMountPoint" : "~NAME~/run",
"provisions" : [],
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
"validLinkPrefixes" : [ "/tmp/",
"/run/",
"/opt/usr/data/",
"switchToDefaultAfterTimeout" : true,
"runMountPoint" : "~NAME~/run",
"provisions" : [],
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
"validLinkPrefixes" : [ "/tmp/",
"/run/",
"/opt/usr/data/",
return;
}
- if (methodName == api::dbus::METHOD_NOTIFY_ACTIVE_ZONE) {
- api::NotifActiveZoneIn data;
- config::loadFromGVariant(parameters, data);
-
- auto rb = std::make_shared<api::DbusMethodResultBuilder<api::Void>>(result);
- mZonesManagerPtr->handleNotifyActiveZoneCall(EMPTY_CALLER, data, rb);
- return;
- }
-
- if (methodName == api::dbus::METHOD_FILE_MOVE_REQUEST) {
- api::FileMoveRequestIn data;
- config::loadFromGVariant(parameters, data);
-
- auto rb = std::make_shared<api::DbusMethodResultBuilder<api::FileMoveRequestStatus>>(result);
- mZonesManagerPtr->handleFileMoveCall(EMPTY_CALLER, data, rb);
- return;
- }
-
if (methodName == api::dbus::METHOD_CREATE_FILE) {
api::CreateFileIn data;
config::loadFromGVariant(parameters, data);
callback);
}
-void HostDbusConnection::sendNotification(const api::Notification& notify)
-{
- GVariant* parameters = g_variant_new("(sss)",
- notify.zone.c_str(),
- notify.application.c_str(),
- notify.message.c_str());
- mDbusConnection->emitSignal(api::dbus::OBJECT_PATH,
- api::dbus::INTERFACE,
- api::dbus::SIGNAL_NOTIFICATION,
- parameters);
-}
-
} // namespace vasum
void setProxyCallCallback(const ProxyCallCallback& callback);
/**
- * Send notification signal to this zone
- */
- void sendNotification(const api::Notification& notify);
-
- /**
* Make a proxy call
*/
void proxyCallAsync(const std::string& busName,
const std::string METHOD_UNLOCK_QUEUE = "UnlockQueue";
const std::string METHOD_SWITCH_TO_DEFAULT = "SwitchToDefault";
-const std::string METHOD_NOTIFY_ACTIVE_ZONE = "NotifyActiveZone";
-const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest";
-const std::string SIGNAL_NOTIFICATION = "Notification";
-
-const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND";
-const std::string FILE_MOVE_WRONG_DESTINATION = "FILE_MOVE_WRONG_DESTINATION";
-const std::string FILE_MOVE_NO_PERMISSIONS_SEND = "FILE_MOVE_NO_PERMISSIONS_SEND";
-const std::string FILE_MOVE_NO_PERMISSIONS_RECEIVE = "FILE_MOVE_NO_PERMISSIONS_RECEIVE";
-const std::string FILE_MOVE_FAILED = "FILE_MOVE_FAILED";
-const std::string FILE_MOVE_SUCCEEDED = "FILE_MOVE_SUCCEEDED";
-
-
const std::string DEFINITION =
"<node>"
" <interface name='" + INTERFACE + "'>"
" <arg type='s' name='id' direction='in'/>"
" <arg type='s' name='device' direction='in'/>"
" </method>"
- " <method name='" + METHOD_NOTIFY_ACTIVE_ZONE + "'>"
- " <arg type='s' name='application' direction='in'/>"
- " <arg type='s' name='message' direction='in'/>"
- " </method>"
- " <method name='" + METHOD_FILE_MOVE_REQUEST + "'>"
- " <arg type='s' name='destination' direction='in'/>"
- " <arg type='s' name='path' direction='in'/>"
- " <arg type='s' name='result' direction='out'/>"
- " </method>"
" <method name='" + METHOD_PROXY_CALL + "'>"
" <arg type='s' name='target' direction='in'/>"
" <arg type='s' name='busName' direction='in'/>"
" </method>"
" <method name='" + METHOD_SWITCH_TO_DEFAULT + "'>"
" </method>"
- " <signal name='" + SIGNAL_NOTIFICATION + "'>"
- " <arg type='s' name='zone'/>"
- " <arg type='s' name='application'/>"
- " <arg type='s' name='message'/>"
- " </signal>"
" </interface>"
"</node>";
setRevokeDeviceCallback(std::bind(&ZonesManager::handleRevokeDeviceCall,
mZonesManagerPtr, _1, _2));
- setNotifyActiveZoneCallback(std::bind(&ZonesManager::handleNotifyActiveZoneCall,
- mZonesManagerPtr, "", _1, _2));
-
setSwitchToDefaultCallback(std::bind(&ZonesManager::handleSwitchToDefaultCall,
mZonesManagerPtr, "", _1));
- setFileMoveCallback(std::bind(&ZonesManager::handleFileMoveCall,
- mZonesManagerPtr, "", _1, _2));
-
setCreateFileCallback(std::bind(&ZonesManager::handleCreateFileCall,
mZonesManagerPtr, _1, _2));
}
Callback::getWrapper(callback));
}
-void HostIPCConnection::setNotifyActiveZoneCallback(
- const Method<const vasum::api::NotifActiveZoneIn>::type& callback)
-{
- typedef IPCMethodWrapper<const api::NotifActiveZoneIn> Method;
- mService->setMethodHandler<Method::out, Method::in>(
- api::ipc::METHOD_NOTIFY_ACTIVE_ZONE,
- Method::getWrapper(callback));
-}
-
void HostIPCConnection::setSwitchToDefaultCallback(const Method<api::Void>::type& callback)
{
typedef IPCMethodWrapper<api::Void> Callback;
Callback::getWrapper(callback));
}
-void HostIPCConnection::setFileMoveCallback(const Method<const api::FileMoveRequestIn,
- api::FileMoveRequestStatus>::type& callback)
-{
- typedef IPCMethodWrapper<const api::FileMoveRequestIn, api::FileMoveRequestStatus> Method;
- mService->setMethodHandler<Method::out, Method::in>(
- api::ipc::METHOD_FILE_MOVE_REQUEST,
- Method::getWrapper(callback));
-}
-
void HostIPCConnection::setCreateFileCallback(const Method<const api::CreateFileIn,
api::CreateFileOut>::type& callback)
{
Method::getWrapper(callback));
}
-void HostIPCConnection::sendNotification(const api::Notification& notification)
-{
- mService->signal(api::ipc::SIGNAL_NOTIFICATION,
- std::make_shared<api::Notification>(notification));
-}
-
} // namespace vasum
void start();
void signalZoneConnectionState(const api::ConnectionState& connectionState);
- void sendNotification(const api::Notification& notification);
private:
void setLockQueueCallback(const Method<api::Void>::type& callback);
void setUnlockZoneCallback(const Method<const api::ZoneId>::type& callback);
void setGrantDeviceCallback(const Method<const api::GrantDeviceIn>::type& callback);
void setRevokeDeviceCallback(const Method<const api::RevokeDeviceIn>::type& callback);
- void setNotifyActiveZoneCallback(const Method<const vasum::api::NotifActiveZoneIn>::type& callback);
void setSwitchToDefaultCallback(const Method<api::Void>::type& callback);
- void setFileMoveCallback(const Method<const api::FileMoveRequestIn,
- api::FileMoveRequestStatus>::type& callback);
void setCreateFileCallback(const Method<const api::CreateFileIn, api::CreateFileOut>::type& callback);
std::unique_ptr<ipc::Service> mService;
const ::ipc::MethodID METHOD_UNLOCK_QUEUE = 29;
const ::ipc::MethodID METHOD_SWITCH_TO_DEFAULT = 30;
-const ::ipc::MethodID METHOD_NOTIFY_ACTIVE_ZONE = 100;
-const ::ipc::MethodID METHOD_FILE_MOVE_REQUEST = 101;
-const ::ipc::MethodID SIGNAL_NOTIFICATION = 102;
-
-const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND";
-const std::string FILE_MOVE_WRONG_DESTINATION = "FILE_MOVE_WRONG_DESTINATION";
-const std::string FILE_MOVE_NO_PERMISSIONS_SEND = "FILE_MOVE_NO_PERMISSIONS_SEND";
-const std::string FILE_MOVE_NO_PERMISSIONS_RECEIVE = "FILE_MOVE_NO_PERMISSIONS_RECEIVE";
-const std::string FILE_MOVE_FAILED = "FILE_MOVE_FAILED";
-const std::string FILE_MOVE_SUCCEEDED = "FILE_MOVE_SUCCEEDED";
-
} // namespace ipc
} // namespace api
} // namespace vasum
std::int64_t cpuQuotaBackground;
/**
- * When you move a file out of the zone (by move request)
- * its path must match at least one of the regexps in this vector.
- */
- std::vector<std::string> permittedToSend;
-
- /**
- * When you move a file to the zone (by move request)
- * its path must match at least one of the regexps in this vector.
- */
- std::vector<std::string> permittedToRecv;
-
- /**
* Valid hard link prefixes.
*/
std::vector<std::string> validLinkPrefixes;
switchToDefaultAfterTimeout, // TODO move to dynamic and add an API to change
cpuQuotaForeground,
cpuQuotaBackground,
- permittedToSend, // TODO move to dynamic and add an API to change
- permittedToRecv, // TODO move to dynamic and add an API to change
validLinkPrefixes,
shutdownTimeout
)
config::loadFromKVStoreWithJsonFile(dbPath, zoneTemplatePath, mConfig, dbPrefix);
config::loadFromKVStoreWithJsonFile(dbPath, zoneTemplatePath, mDynamicConfig, dbPrefix);
- for (std::string r: mConfig.permittedToSend) {
- mPermittedToSend.push_back(boost::regex(r));
- }
- for (std::string r: mConfig.permittedToRecv) {
- mPermittedToRecv.push_back(boost::regex(r));
- }
-
if (!mDynamicConfig.runMountPoint.empty()) {
mRunMountPoint = fs::absolute(mDynamicConfig.runMountPoint, baseRunMountPointPath).string();
}
LOGD(mId << ": Zone object destroyed");
}
-const std::vector<boost::regex>& Zone::getPermittedToSend() const
-{
- return mPermittedToSend;
-}
-
-const std::vector<boost::regex>& Zone::getPermittedToRecv() const
-{
- return mPermittedToRecv;
-}
-
const std::string& Zone::getId() const
{
Lock lock(mReconnectMutex);
typedef std::function<void(bool succeeded)> StartAsyncResultCallback;
/**
- * Returns a vector of regexps defining files permitted to be
- * send to other zones using file move functionality
- */
- const std::vector<boost::regex>& getPermittedToSend() const;
-
- /**
- * Returns a vector of regexps defining files permitted to be
- * send to other zones using file move functionality
- */
- const std::vector<boost::regex>& getPermittedToRecv() const;
-
- /**
* Get the zone id
*/
const std::string& getId() const;
private:
ZoneConfig mConfig;
ZoneDynamicConfig mDynamicConfig;
- std::vector<boost::regex> mPermittedToSend;
- std::vector<boost::regex> mPermittedToRecv;
std::unique_ptr<ZoneProvision> mProvision;
mutable std::recursive_mutex mReconnectMutex;
std::string mRunMountPoint;
namespace {
-#ifdef ZONE_CONNECTION
-bool regexMatchVector(const std::string& str, const std::vector<boost::regex>& v)
-{
- for (const boost::regex& toMatch : v) {
- if (boost::regex_match(str, toMatch)) {
- return true;
- }
- }
-
- return false;
-}
-#endif
const std::string HOST_ID = "host";
const std::string ENABLED_FILE_NAME = "enabled";
tryAddTask(handler, result, true);
}
-#ifdef ZONE_CONNECTION
-void ZonesManager::handleNotifyActiveZoneCall(const std::string& caller,
- const api::NotifActiveZoneIn& notif,
- api::MethodResultBuilder::Pointer result)
-{
- auto handler = [&, this] {
- const std::string& application = notif.first;
- const std::string& message = notif.second;
- LOGI("handleNotifyActiveZoneCall(" << caller << ", " << application << ", " << message
- << ") called");
-
- Lock lock(mMutex);
-
- try {
- auto iter = getRunningForegroundZoneIterator();
- if (iter != mZones.end() && caller != get(iter).getId()) {
- //XXX:get(iter).sendNotification(caller, application, message);
- }
- result->setVoid();
- } catch (const std::runtime_error&) {
- LOGE("Notification from " << caller << " hasn't been sent");
- result->setError(api::ERROR_INTERNAL, "Notification hasn't been sent");
- }
- };
-
- tryAddTask(handler, result, true);
-}
-
-void ZonesManager::handleFileMoveCall(const std::string& srcZoneId,
- const api::FileMoveRequestIn& request,
- api::MethodResultBuilder::Pointer result)
-{
- // TODO: this implementation is only a placeholder.
- // There are too many unanswered questions and security concerns:
- // 1. What about mount namespace, host might not see the source/destination
- // file. The file might be a different file from a host perspective.
- // 2. Copy vs move (speed and security concerns over already opened FDs)
- // 3. Access to source and destination files - DAC, uid/gig
- // 4. Access to source and destintation files - MAC, smack
- // 5. Destination file uid/gid assignment
- // 6. Destination file smack label assignment
- // 7. Verifiability of the source path
-
- // NOTE: other possible implementations include:
- // 1. Sending file descriptors opened directly in each zone through DBUS
- // using something like g_dbus_message_set_unix_fd_list()
- // 2. VSM forking and calling setns(MNT) in each zone and opening files
- // by itself, then passing FDs to the main process
- // Now when the main process has obtained FDs (by either of those methods)
- // it can do the copying by itself.
-
- auto handler = [&, this] {
- const std::string& dstZoneId = request.first;
- const std::string& path = request.second;
- LOGI("File move requested\n"
- << "src: " << srcZoneId << "\n"
- << "dst: " << dstZoneId << "\n"
- << "path: " << path);
-
- Lock lock(mMutex);
-
- auto srcIter = findZone(srcZoneId);
- if (srcIter == mZones.end()) {
- LOGE("Source zone '" << srcZoneId << "' not found");
- return;
- }
- Zone& srcZone = get(srcIter);
-
- auto status = std::make_shared<api::FileMoveRequestStatus>();
-
- auto dstIter = findZone(dstZoneId);
- if (dstIter == mZones.end()) {
- LOGE("Destination zone '" << dstZoneId << "' not found");
- status->value = api::FILE_MOVE_DESTINATION_NOT_FOUND;
- result->set(status);
- return;
- }
- Zone& dstContanier = get(dstIter);
-
- if (srcZoneId == dstZoneId) {
- LOGE("Cannot send a file to yourself");
- status->value = api::FILE_MOVE_WRONG_DESTINATION;
- result->set(status);
- return;
- }
-
- if (!regexMatchVector(path, srcZone.getPermittedToSend())) {
- LOGE("Source zone has no permissions to send the file: " << path);
- status->value = api::FILE_MOVE_NO_PERMISSIONS_SEND;
- result->set(status);
- return;
- }
-
- if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) {
- LOGE("Destination zone has no permissions to receive the file: " << path);
- status->value = api::FILE_MOVE_NO_PERMISSIONS_RECEIVE;
- result->set(status);
- return;
- }
-
- namespace fs = boost::filesystem;
- std::string srcPath = fs::absolute(srcZoneId, mConfig.zonesPath).string() + path;
- std::string dstPath = fs::absolute(dstZoneId, mConfig.zonesPath).string() + path;
-
- if (!utils::moveFile(srcPath, dstPath)) {
- LOGE("Failed to move the file: " << path);
- status->value = api::FILE_MOVE_FAILED;
- result->set(status);
- } else {
- status->value = api::FILE_MOVE_SUCCEEDED;
- result->set(status);
- try {
- //XXX: dstContanier.sendNotification(srcZoneId, path, api::FILE_MOVE_SUCCEEDED);
- } catch (ServerException&) {
- LOGE("Notification to '" << dstZoneId << "' has not been sent");
- }
- }
- };
-
- tryAddTask(handler, result, true);
-}
-#else
-void ZonesManager::handleNotifyActiveZoneCall(const std::string& /* caller */,
- const api::NotifActiveZoneIn& /*notif*/,
- api::MethodResultBuilder::Pointer result)
-{
- result->setError(api::ERROR_INTERNAL, "Not implemented");
-}
-
-void ZonesManager::handleFileMoveCall(const std::string& /*srcZoneId*/,
- const api::FileMoveRequestIn& /*request*/,
- api::MethodResultBuilder::Pointer result)
-{
- result->setError(api::ERROR_INTERNAL, "Not implemented");
-}
-
-#endif /* ZONE_CONNECTION */
-
void ZonesManager::handleCreateFileCall(const api::CreateFileIn& request,
api::MethodResultBuilder::Pointer result)
{
api::MethodResultBuilder::Pointer result);
void handleCreateFileCall(const api::CreateFileIn& request,
api::MethodResultBuilder::Pointer result);
-
- // Zone's handlers---------------------------------------------------------
- void handleNotifyActiveZoneCall(const std::string& caller,
- const api::NotifActiveZoneIn& notif,
- api::MethodResultBuilder::Pointer result);
void handleSwitchToDefaultCall(const std::string& caller,
api::MethodResultBuilder::Pointer result);
- void handleFileMoveCall(const std::string& srcZoneId,
- const api::FileMoveRequestIn& request,
- api::MethodResultBuilder::Pointer result);
private:
typedef std::recursive_mutex Mutex;
vsm_client_free(client);
}
-#ifdef ZONE_CONNECTION
-BOOST_AUTO_TEST_CASE(FileMoveRequest)
-{
- const std::string path = "/tmp/fake_path";
- const std::string secondZone = "fake_zone";
-
- VsmClient client = vsm_client_create();
- VsmStatus status = vsm_connect(client);
- BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
- status = vsm_file_move_request(client, secondZone.c_str(), path.c_str());
- BOOST_REQUIRE_EQUAL(VSMCLIENT_CUSTOM_ERROR, status);
- BOOST_REQUIRE_EQUAL(api::FILE_MOVE_DESTINATION_NOT_FOUND,
- vsm_get_status_message(client));
- vsm_client_free(client);
-}
-
-BOOST_AUTO_TEST_CASE(Notification)
-{
- const std::string MSG_CONTENT = "msg";
- const std::string MSG_APP = "app";
-
- struct CallbackData {
- Latch signalReceivedLatch;
- std::vector< std::tuple<std::string, std::string, std::string> > receivedSignalMsg;
- };
-
- auto callback = [](const char* zone,
- const char* application,
- const char* message,
- void* data) {
- CallbackData& callbackData = *reinterpret_cast<CallbackData*>(data);
- callbackData.receivedSignalMsg.push_back(std::make_tuple(zone, application, message));
- callbackData.signalReceivedLatch.set();
- };
-
- CallbackData callbackData;
- std::map<std::string, VsmClient> clients;
- for (const auto& it : EXPECTED_ZONES) {
- VsmClient client = vsm_client_create();
- VsmStatus status = vsm_connect_custom(client, it.c_str());
- BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
- clients[it.first] = client;
- }
- for (auto& client : clients) {
- VsmStatus status = vsm_add_notification_callback(client.second,
- callback,
- &callbackData,
- NULL);
- BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
- }
- for (auto& client : clients) {
- VsmStatus status = vsm_notify_active_zone(client.second,
- MSG_APP.c_str(),
- MSG_CONTENT.c_str());
- BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
- }
-
- BOOST_CHECK(callbackData.signalReceivedLatch.waitForN(clients.size() - 1u, EVENT_TIMEOUT));
- BOOST_CHECK(callbackData.signalReceivedLatch.empty());
-
- for (const auto& msg : callbackData.receivedSignalMsg) {
- BOOST_CHECK(clients.count(std::get<0>(msg)) > 0);
- BOOST_CHECK_EQUAL(std::get<1>(msg), MSG_APP);
- BOOST_CHECK_EQUAL(std::get<2>(msg), MSG_CONTENT);
- }
-
- for (auto& client : clients) {
- vsm_client_free(client.second);
- }
-}
-#endif
-
BOOST_AUTO_TEST_CASE(GetZoneIdByPidTestSingle)
{
VsmClient client = vsm_client_create();
"shutdownTimeout" : 10,
"runMountPoint" : "",
"provisions" : [],
- "permittedToSend" : [],
- "permittedToRecv" : [],
"validLinkPrefixes" : []
}
"shutdownTimeout" : 10,
"runMountPoint" : "",
"provisions" : [],
- "permittedToSend" : [],
- "permittedToRecv" : [],
"validLinkPrefixes" : []
}
"shutdownTimeout" : 10,
"runMountPoint" : "/tmp/ut-run/~NAME~",
"provisions" : [],
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
"validLinkPrefixes" : []
}
"shutdownTimeout" : 10,
"runMountPoint" : "/tmp/ut-run/~NAME~",
"provisions" : [],
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
"validLinkPrefixes" : []
}
"shutdownTimeout" : 10,
"runMountPoint" : "",
"provisions" : [],
- "permittedToSend" : [],
- "permittedToRecv" : [],
"validLinkPrefixes" : [ "/tmp" ]
}
"shutdownTimeout" : 10,
"runMountPoint" : "",
"provisions" : [],
- "permittedToSend" : [],
- "permittedToRecv" : [],
"validLinkPrefixes" : []
}
"shutdownTimeout" : 10,
"runMountPoint" : "",
"provisions" : [],
- "permittedToSend" : [],
- "permittedToRecv" : [],
"validLinkPrefixes" : []
}
MethodResultBuilder::Pointer result
)> TestApiMethodCallback;
typedef std::function<void()> VoidResultCallback;
- typedef std::function<void(const api::Notification)> NotificationCallback;
typedef std::map<std::string, std::string> Connections;
HostDbusAccessory()
mClient->signalSubscribe(callback, isHost() ? api::dbus::BUS_NAME : api::dbus::BUS_NAME);
}
- void subscribeNotification(const NotificationCallback& callback)
- {
- auto handler = [callback](const std::string& /*senderBusName*/,
- const std::string& objectPath,
- const std::string& interface,
- const std::string& signalName,
- GVariant* parameters)
- {
- if (objectPath == api::dbus::OBJECT_PATH &&
- interface == api::dbus::INTERFACE &&
- signalName == api::dbus::SIGNAL_NOTIFICATION &&
- g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) {
-
- const gchar* zone = NULL;
- const gchar* application = NULL;
- const gchar* message = NULL;
- g_variant_get(parameters, "(&s&s&s)", &zone, &application, &message);
- callback({zone, application, message});
- }
- };
- mClient->signalSubscribe(handler, api::dbus::BUS_NAME);
- }
-
void callSwitchToDefault()
{
mClient->callMethod(api::dbus::BUS_NAME,
"()");
}
- void callMethodNotify()
- {
- GVariant* parameters = g_variant_new("(ss)", TEST_APP_NAME.c_str(), TEST_MESSAGE.c_str());
- mClient->callMethod(api::dbus::BUS_NAME,
- api::dbus::OBJECT_PATH,
- api::dbus::INTERFACE,
- api::dbus::METHOD_NOTIFY_ACTIVE_ZONE,
- parameters,
- "()");
- }
-
- std::string callMethodMove(const std::string& dest, const std::string& path)
- {
- GVariant* parameters = g_variant_new("(ss)", dest.c_str(), path.c_str());
- GVariantPtr result = mClient->callMethod(api::dbus::BUS_NAME,
- api::dbus::OBJECT_PATH,
- api::dbus::INTERFACE,
- api::dbus::METHOD_FILE_MOVE_REQUEST,
- parameters,
- "(s)");
-
- const gchar* retcode = NULL;
- g_variant_get(result.get(), "(&s)", &retcode);
- return std::string(retcode);
- }
-
void registerTestApiObject(const TestApiMethodCallback& callback)
{
auto handler = [callback](const std::string& objectPath,
class HostIPCAccessory {
public:
typedef std::function<void()> VoidResultCallback;
- typedef std::function<void(const api::Notification)> NotificationCallback;
HostIPCAccessory()
: mClient(mDispatcher.getPoll(), HOST_IPC_SOCKET)
EVENT_TIMEOUT*10); //Prevent from IPCTimeoutException see LockUnlockZone
}
- void subscribeNotification(const NotificationCallback& callback)
- {
- auto callbackWrapper = [callback] (const ipc::PeerID, std::shared_ptr<api::Notification>& data) {
- callback(*data);
- };
- mClient.setSignalHandler<api::Notification>(api::ipc::SIGNAL_NOTIFICATION,
- callbackWrapper);
- }
-
void callSwitchToDefault()
{
mClient.callSync<api::Void, api::Void>(api::ipc::METHOD_SWITCH_TO_DEFAULT,
EVENT_TIMEOUT*10); //Prevent from IPCTimeoutException see LockUnlockZone
}
- void callMethodNotify()
- {
- mClient.callSync<api::NotifActiveZoneIn, api::Void>(
- api::ipc::METHOD_NOTIFY_ACTIVE_ZONE,
- std::make_shared<api::NotifActiveZoneIn>(api::NotifActiveZoneIn{TEST_APP_NAME, TEST_MESSAGE}),
- EVENT_TIMEOUT*10); //Prevent from IPCTimeoutException see LockUnlockZone
- }
-
- std::string callMethodMove(const std::string& dest, const std::string& path)
- {
- auto result = mClient.callSync<api::FileMoveRequestIn, api::FileMoveRequestStatus>(
- api::ipc::METHOD_FILE_MOVE_REQUEST,
- std::make_shared<api::FileMoveRequestIn>(api::FileMoveRequestIn{dest, path}),
- EVENT_TIMEOUT*10);
- return result->value;
- }
-
int callMethodCreateFile(const std::string& id,
const std::string& path,
const std::int32_t& flags,
BOOST_CHECK(cm.getRunningForegroundZoneId() == "zone3");
}
-#ifdef ZONE_CONNECTION
-BOOST_AUTO_TEST_CASE(NotifyActiveZone)
-{
- ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH);
- cm.createZone("zone1", SIMPLE_TEMPLATE);
- cm.createZone("zone2", SIMPLE_TEMPLATE);
- cm.createZone("zone3", SIMPLE_TEMPLATE);
- cm.restoreAll();
-
- Latch signalReceivedLatch;
- std::map<int, std::vector<std::string>> signalReceivedSourcesMap;
-
- std::map<int, std::unique_ptr<ZoneAccessory>> connections;
- for (int i = 1; i <= TEST_DBUS_CONNECTION_ZONES_COUNT; ++i) {
- connections[i] = std::unique_ptr<ZoneAccessory>(new ZoneAccessory(i));
- }
-
- auto handler = [](Latch& latch,
- std::vector<std::string>& receivedSignalSources,
- const api::Notification& notify)
- {
- receivedSignalSources.push_back(notify.zone);
- if (notify.application == TEST_APP_NAME && notify.message == TEST_MESSAGE) {
- latch.set();
- }
- };
-
- using namespace std::placeholders;
- for (int i = 1; i <= TEST_DBUS_CONNECTION_ZONES_COUNT; ++i) {
- connections[i]->subscribeNotification(std::bind(handler,
- std::ref(signalReceivedLatch),
- std::ref(signalReceivedSourcesMap[i]),
- _1));
- }
- for (auto& connection : connections) {
- connection.second->callMethodNotify();
- }
-
- BOOST_REQUIRE(signalReceivedLatch.waitForN(connections.size() - 1u, EVENT_TIMEOUT));
- BOOST_REQUIRE(signalReceivedLatch.empty());
-
- //check if there are no signals that was received more than once
- for (const auto& source : signalReceivedSourcesMap[1]) {
- BOOST_CHECK_EQUAL(std::count(signalReceivedSourcesMap[1].begin(),
- signalReceivedSourcesMap[1].end(),
- source), 1);
- }
- //check if all signals was received by active zone
- BOOST_CHECK_EQUAL(signalReceivedSourcesMap[1].size(), connections.size() - 1);
- //check if no signals was received by inactive zone
- for (size_t i = 2; i <= connections.size(); ++i) {
- BOOST_CHECK(signalReceivedSourcesMap[i].empty());
- }
-
- connections.clear();
-}
-
-BOOST_AUTO_TEST_CASE(MoveFile)
-{
- ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH);
- cm.createZone("zone1", SIMPLE_TEMPLATE);
- cm.createZone("zone2", SIMPLE_TEMPLATE);
- cm.createZone("zone3", SIMPLE_TEMPLATE);
- cm.restoreAll();
-
- Latch notificationLatch;
- std::string notificationSource;
- std::string notificationPath;
- std::string notificationRetcode;
-
- std::map<int, std::unique_ptr<ZoneAccessory>> connections;
- for (int i = 1; i <= 2; ++i) {
- connections[i] = std::unique_ptr<ZoneAccessory>(new ZoneAccessory(i));
- }
-
- auto handler = [&](const api::Notification& notify)
- {
- notificationSource = notify.zone;
- notificationPath = notify.application;
- notificationRetcode = notify.message;
- notificationLatch.set();
- };
-
- // subscribe the second (destination) zone for notifications
- connections.at(2)->subscribeNotification(handler);
-
- const std::string TMP = "/tmp/ut-zones";
- const std::string NO_PATH = "path_doesnt_matter_here";
- const std::string BUGGY_PATH = TMP + "/this_file_does_not_exist";
- const std::string BUGGY_ZONE = "this-zone-does-not-exist";
- const std::string ZONE1 = "zone1";
- const std::string ZONE2 = "zone2";
- const std::string ZONE1PATH = TMP + "/" + ZONE1 + TMP;
- const std::string ZONE2PATH = TMP + "/" + ZONE2 + TMP;
-
- // sending to a non existing zone
- BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(BUGGY_ZONE, NO_PATH),
- api::FILE_MOVE_DESTINATION_NOT_FOUND);
- BOOST_CHECK(notificationLatch.empty());
-
- // sending to self
- BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(ZONE1, NO_PATH),
- api::FILE_MOVE_WRONG_DESTINATION);
- BOOST_CHECK(notificationLatch.empty());
-
- // no permission to send
- BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(ZONE2, "/etc/secret1"),
- api::FILE_MOVE_NO_PERMISSIONS_SEND);
- BOOST_CHECK(notificationLatch.empty());
-
- // no permission to receive
- // TODO uncomment this after adding an api to change 'permittedTo*' config
- //BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(ZONE2, "/etc/secret2"),
- // api::FILE_MOVE_NO_PERMISSIONS_RECEIVE);
- //BOOST_CHECK(notificationLatch.empty());
-
- // non existing file
- BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(ZONE2, BUGGY_PATH),
- api::FILE_MOVE_FAILED);
- BOOST_CHECK(notificationLatch.empty());
-
- // a working scenario
- namespace fs = boost::filesystem;
- boost::system::error_code ec;
- fs::remove_all(ZONE1PATH, ec);
- fs::remove_all(ZONE2PATH, ec);
- BOOST_REQUIRE(fs::create_directories(ZONE1PATH, ec));
- BOOST_REQUIRE(fs::create_directories(ZONE2PATH, ec));
- BOOST_REQUIRE(utils::saveFileContent(ZONE1PATH + "/file", FILE_CONTENT));
-
- BOOST_CHECK_EQUAL(connections.at(1)->callMethodMove(ZONE2, TMP + "/file"),
- api::FILE_MOVE_SUCCEEDED);
- BOOST_REQUIRE(notificationLatch.wait(EVENT_TIMEOUT));
- BOOST_REQUIRE(notificationLatch.empty());
- BOOST_CHECK_EQUAL(notificationSource, ZONE1);
- BOOST_CHECK_EQUAL(notificationPath, TMP + "/file");
- BOOST_CHECK_EQUAL(notificationRetcode, api::FILE_MOVE_SUCCEEDED);
- BOOST_CHECK(!fs::exists(ZONE1PATH + "/file"));
- BOOST_CHECK_EQUAL(utils::readFileContent(ZONE2PATH + "/file"), FILE_CONTENT);
-
- fs::remove_all(ZONE1PATH, ec);
- fs::remove_all(ZONE2PATH, ec);
-}
-#endif
-
MULTI_FIXTURE_TEST_CASE(SwitchToDefault, F, ACCESSORS)
{
ZonesManager cm(F::dispatcher.getPoll(), TEST_CONFIG_PATH);