* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. */
+#include <algorithm>
#include <iostream>
#include <memory>
#include <gio/gio.h>
struct introspection_data {
- introspection_data(const std::string_view &xml)
+ introspection_data(std::string_view xml)
{
inner = g_dbus_node_info_new_for_xml(xml.data(), nullptr);
- if (inner == nullptr) {
- throw std::system_error(std::error_code(), "Couldn't parse introspection data"); // TODO
- }
+ if (inner == nullptr)
+ throw std::system_error(std::error_code(), "Couldn't parse introspection data");
}
~introspection_data()
};
struct owner_id {
- owner_id(const std::string_view &name, GBusAcquiredCallback on_connect, GBusNameLostCallback on_error,
+ owner_id(std::string_view name, GBusAcquiredCallback on_connect, GBusNameLostCallback on_error,
gpointer user_data)
{
inner = g_bus_own_name(G_BUS_TYPE_SYSTEM, name.data(), G_BUS_NAME_OWNER_FLAGS_NONE, on_connect,
{
guint registration_id = g_dbus_connection_register_object(
connection, bus_object.data(), data.inner->interfaces[0], &table, nullptr, nullptr, nullptr);
- if (registration_id <= 0) {
- throw std::system_error(std::error_code(), "Couldn't register ID"); // TODO
- }
+ if (registration_id <= 0)
+ throw std::system_error(std::error_code(), "Couldn't register ID");
}
void on_name_lost(GDBusConnection *connection)
{
- throw std::system_error(std::error_code(), "Name lost"); // TODO
+ throw std::system_error(std::error_code(), "Name lost");
+ }
+
+ void on_add_user(GDBusMethodInvocation *invocation, GVariant *parameters)
+ {
+ if (!g_variant_is_of_type(parameters, g_variant_type_new("(ii)")))
+ throw std::system_error(std::error_code(), "Invalid parameters type");
+
+ int session_uid;
+ int subsession_id;
+ g_variant_get(parameters, "(ii)", &session_uid, &subsession_id);
+
+ if (session_uid <= 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ return;
+ }
+
+ g_dbus_method_invocation_return_value(invocation, nullptr);
+ }
+
+ void on_remove_user(GDBusMethodInvocation *invocation, GVariant *parameters)
+ {
+ if (!g_variant_is_of_type(parameters, g_variant_type_new("(ii)")))
+ throw std::system_error(std::error_code(), "Invalid parameters type");
+
+ int session_uid;
+ int subsession_id;
+ g_variant_get(parameters, "(ii)", &session_uid, &subsession_id);
+
+ if (session_uid <= 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ return;
+ }
+
+ g_dbus_method_invocation_return_value(invocation, nullptr);
}
- void on_method_call(const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation)
+ void on_switch_user(GDBusMethodInvocation *invocation, GVariant *parameters)
{
- std::string_view name = method_name;
+ if (!g_variant_is_of_type(parameters, g_variant_type_new("(iii)")))
+ throw std::system_error(std::error_code(), "Invalid parameters type");
+
+ int session_uid;
+ int prev_subsession_id;
+ int next_subsession_id;
+ g_variant_get(parameters, "(iii)", &session_uid, &prev_subsession_id, &next_subsession_id);
- if (name == "Run") {
- g_dbus_method_invocation_return_value(invocation, nullptr);
- } else {
- throw std::system_error(std::error_code(), "Unknown method"); // TODO
+ if (session_uid <= 0) {
+ g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+ return;
}
+
+ g_dbus_method_invocation_return_value(invocation, nullptr);
}
static void glib_bus_connected(GDBusConnection *connection, const gchar *name, gpointer user_data)
const gchar *interface_name, const gchar *method_name, GVariant *parameters,
GDBusMethodInvocation *invocation, gpointer user_data)
{
- auto self = static_cast<sessiond_context *>(user_data);
- self->on_method_call(method_name, parameters, invocation);
+ // TODO: Also dispatch on interface_name (not needed at the moment)
+ try {
+ auto self = static_cast<sessiond_context *>(user_data);
+ auto to_call = std::find_if(methods.begin(), methods.end(), [&](auto pair) {
+ return pair.first == method_name;
+ });
+ if (to_call == methods.end())
+ throw std::system_error(std::error_code(), std::string("Unknown method ") + method_name + " called");
+ std::cout << "Handling " << method_name << " call from " << sender << std::endl;
+ (self->*(to_call->second))(invocation, parameters);
+ } catch (const std::exception &ex) {
+ std::cerr << "Exception " << ex.what() << "\n" <<
+ "while handling " << method_name << " call from " << sender << "\n";
+ // Swallow the exception; the show must go on
+ }
}
constexpr static GDBusInterfaceVTable table = {
constexpr static std::string_view xml =
"<node name=\"/org/tizen/sessiond\">"
- "<interface name=\"org.tizen.sessiond.HelloWorld\">"
- "<method name=\"Run\"> </method>"
+ "<interface name=\"org.tizen.sessiond.subsession.Manager\">"
+ "<method name=\"AddUser\">"
+ "<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "</method>"
+ "<method name=\"RemoveUser\">"
+ "<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "</method>"
+ "<method name=\"SwitchUser\">"
+ "<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"prev_subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"next_subsession_id\" type=\"i\" direction=\"in\"/>"
+ "</method>"
"</interface>"
"</node>";
constexpr static std::string_view bus_name = "org.tizen.sessiond";
constexpr static std::string_view bus_object = "/org/tizen/sessiond";
+ constexpr static std::array<
+ std::pair<
+ std::string_view,
+ void (sessiond_context::*)(GDBusMethodInvocation *, GVariant *)
+ >, 3> methods = {
+ std::make_pair("AddUser", &sessiond_context::on_add_user),
+ std::make_pair("RemoveUser", &sessiond_context::on_remove_user),
+ std::make_pair("SwitchUser", &sessiond_context::on_switch_user),
+ };
+
introspection_data data;
owner_id id;
main_loop loop;