--- /dev/null
+/* MIT License
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE. */
+
+#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ const char *dbus_error_msg;
+ int code;
+} error_mapping_t;
+
+static error_mapping_t error_mappings[] = {
+ { "org.tizen.sessiond.Error.InvalidParameter", SUBSESSION_ERROR_INVALID_PARAMETER },
+ { "org.tizen.sessiond.Error.IOError", SUBSESSION_ERROR_IO_ERROR },
+ { "org.tizen.sessiond.Error.SubsessionAlreadyExists", SUBSESSION_ERROR_ALREADY_EXISTS },
+ { "org.tizen.sessiond.Error.SubsessionDoesNotExist", SUBSESSION_ERROR_NOT_AVAILABLE },
+};
+
+#ifdef __cplusplus
+}
+#endif
throw std::runtime_error("Bus name lost");
}
+ bool check_parameters_invalid(GDBusMethodInvocation *invocation, const int session_uid, const int subsession_id)
+ {
+ if (session_uid <= 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+ return true;
+ }
+ if (subsession_id <= 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative subsession_id passed");
+ return true;
+ }
+
+ return false;
+ }
+
void on_add_user(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
- if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
- }
GError *err = nullptr;
if (!g_dbus_connection_emit_signal(connection, nullptr, bus_object.data(), bus_iface.data(), "AddUserStarted",
{
auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
- if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
- }
GError *err = nullptr;
if (!g_dbus_connection_emit_signal(connection, nullptr, bus_object.data(), bus_iface.data(), "RemoveUserStarted",
auto [ session_uid, next_subsession_id ] = tuple_from_g_variant<int, int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
+ return;
+ }
+ // N.B. Switch to user '0' is possible and it means no subsession is currently active
+ if (next_subsession_id < 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative subsession_id passed");
return;
}
if (!fs_helpers::subsession_exists(session_uid, next_subsession_id)) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.FileNotFound", "Invalid UID or subsession passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_DOES_NOT_EXIST].second.data(), "Subsession does not exist");
return;
}
auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
{
auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
- if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
- }
wait_add.try_emplace(session_uid, session_uid, connection, "AddUserCompleted");
wait_add.at(session_uid).on_client_done(subsession_id, std::string(sender));
{
auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
- if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
- }
wait_remove.try_emplace(session_uid, session_uid, connection, "RemoveUserCompleted");
wait_remove.at(session_uid).on_client_done(subsession_id, std::string(sender));
auto [ session_uid, switch_id ] = tuple_from_g_variant<int, uint64_t>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
if (session_uid <= 0) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), "Negative UID passed");
return;
}
std::cout << "Handling " << method_name << " call from " << sender << std::endl;
(self->*(to_call->second))(invocation, std::string_view(sender), parameters);
} catch (const std::invalid_argument &ex) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", ex.what());
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_INVALID_PARAMETER].second.data(), ex.what());
+ log_exception(ex, sender, method_name);
+ } catch (const std::system_error &ex) {
+ switch (ex.code().value()) {
+ case EEXIST:
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_ALREADY_EXISTS].second.data(), ex.what());
+ break;
+ case ENOENT:
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_DOES_NOT_EXIST].second.data(), ex.what());
+ break;
+ default:
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_IO_ERROR].second.data(),
+ (std::string("Unable to complete requested operation: ") + ex.what()).c_str());
+ break;
+ }
log_exception(ex, sender, method_name);
} catch (const std::runtime_error &ex) {
- g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.Failed",
- (std::string("Unable to complete requested operation: ") + std::string(ex.what())).c_str());
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ sessiond_errors[SUBSESSION_ERROR_IO_ERROR].second.data(),
+ (std::string("Unable to complete requested operation: ") + ex.what()).c_str());
log_exception(ex, sender, method_name);
// Swallow the exception; the show must go on
}
std::make_pair("GetCurrentUser"sv, &sessiond_context::on_get_current_user),
};
+ enum {
+ SUBSESSION_ERROR_INVALID_PARAMETER,
+ SUBSESSION_ERROR_IO_ERROR,
+ SUBSESSION_ERROR_ALREADY_EXISTS,
+ SUBSESSION_ERROR_DOES_NOT_EXIST,
+ };
+
+ constexpr static std::array sessiond_errors = {
+ std::make_pair(SUBSESSION_ERROR_INVALID_PARAMETER, "org.tizen.sessiond.Error.InvalidParameter"sv),
+ std::make_pair(SUBSESSION_ERROR_IO_ERROR, "org.tizen.sessiond.Error.IOError"sv),
+ std::make_pair(SUBSESSION_ERROR_ALREADY_EXISTS, "org.tizen.sessiond.Error.SubsessionAlreadyExists"sv),
+ std::make_pair(SUBSESSION_ERROR_DOES_NOT_EXIST, "org.tizen.sessiond.Error.SubsessionDoesNotExist"sv),
+ };
+
// TODO: Currently, the first parameter is always a single-element tuple.
// Consider simplifying wait_manager.
// N.B. Although GLib is multi-threaded, the following data structures do not need