2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <types_internal.h>
22 #include <dbus_listener_iface.h>
24 #include "client_request.h"
25 #include "dbus_server_impl.h"
27 static ctx::dbus_server_impl *_instance = NULL;
28 static GDBusConnection *dbus_connection = NULL;
29 static guint dbus_owner_id = 0;
30 static GDBusNodeInfo *dbus_node_info = NULL;
32 static const gchar introspection_xml[] =
34 " <interface name='" DBUS_IFACE "'>"
35 " <method name='" METHOD_REQUEST "'>"
36 " <arg type='i' name='" ARG_REQTYPE "' direction='in'/>"
37 " <arg type='s' name='" ARG_COOKIE "' direction='in'/>"
38 " <arg type='i' name='" ARG_REQID "' direction='in'/>"
39 " <arg type='s' name='" ARG_SUBJECT "' direction='in'/>"
40 " <arg type='s' name='" ARG_INPUT "' direction='in'/>"
41 " <arg type='i' name='" ARG_RESULT_ERR "' direction='out'/>"
42 " <arg type='s' name='" ARG_RESULT_ADD "' direction='out'/>"
43 " <arg type='s' name='" ARG_OUTPUT "' direction='out'/>"
48 static const char* req_type_to_str(int req_type)
66 static void handle_request(const char *sender, GVariant *param, GDBusMethodInvocation *invocation)
69 const gchar *cookie = NULL;
71 const gchar *subject = NULL;
72 const gchar *input = NULL;
74 g_variant_get(param, "(i&si&s&s)", &req_type, &cookie, &req_id, &subject, &input);
75 IF_FAIL_VOID_TAG(req_type > 0 && req_id > 0 && cookie && subject && input, _E, "Invalid request");
77 _SD("Cookie: %s", cookie);
78 _I("[%s] ReqId: %d, Subject: %s", req_type_to_str(req_type), req_id, subject);
79 _SI("Input: %s", input);
81 //TODO: Parameter validation
83 ctx::client_request *request = NULL;
85 request = new ctx::client_request(req_type, sender, req_id, subject, input, cookie, invocation);
86 } catch (std::bad_alloc& ba) {
87 _E("Memory allocation failed");
88 g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", ERR_OPERATION_FAILED, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT));
92 g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", ERR_OPERATION_FAILED, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT));
96 ctx::server::send_request(request);
99 static void handle_method_call(GDBusConnection *conn, const gchar *sender,
100 const gchar *obj_path, const gchar *iface, const gchar *method_name,
101 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
103 IF_FAIL_VOID_TAG(STR_EQ(obj_path, DBUS_PATH), _W, "Invalid path: %s", obj_path);
104 IF_FAIL_VOID_TAG(STR_EQ(iface, DBUS_IFACE), _W, "Invalid interface: %s", obj_path);
106 if (STR_EQ(method_name, METHOD_REQUEST)) {
107 handle_request(sender, param, invocation);
109 _W("Invalid method: %s", method_name);
113 static void on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
115 GDBusInterfaceVTable vtable;
116 vtable.method_call = handle_method_call;
117 vtable.get_property = NULL;
118 vtable.set_property = NULL;
120 guint reg_id = g_dbus_connection_register_object(conn, DBUS_PATH,
121 dbus_node_info->interfaces[0], &vtable, NULL, NULL, NULL);
124 _E("Failed to acquire dbus");
128 dbus_connection = conn;
131 static void on_name_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
133 _SI("Dbus name acquired: %s", name);
136 static void on_name_lost(GDBusConnection *conn, const gchar *name, gpointer user_data)
138 _E("Dbus name lost");
142 ctx::dbus_server_impl::dbus_server_impl()
146 ctx::dbus_server_impl::~dbus_server_impl()
151 bool ctx::dbus_server_impl::init()
153 IF_FAIL_RETURN_TAG(dbus_node_info == NULL, false, _E, "Re-initialization");
155 dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
156 IF_FAIL_RETURN_TAG(dbus_node_info != NULL, false, _E, "Initialization failed");
158 dbus_owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, DBUS_DEST, G_BUS_NAME_OWNER_FLAGS_NONE,
159 on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL);
165 void ctx::dbus_server_impl::release()
167 if (dbus_connection) {
168 g_dbus_connection_flush_sync(dbus_connection, NULL, NULL);
171 if (dbus_owner_id > 0) {
172 g_bus_unown_name(dbus_owner_id);
176 if (dbus_connection) {
177 g_dbus_connection_close_sync(dbus_connection, NULL, NULL);
178 g_object_unref(dbus_connection);
179 dbus_connection = NULL;
182 if (dbus_node_info) {
183 g_dbus_node_info_unref(dbus_node_info);
184 dbus_node_info = NULL;
188 void ctx::dbus_server_impl::publish(const char* dest, int req_id, const char* subject, int error, const char* data)
190 IF_FAIL_VOID_TAG(dest && subject && data, _E, "Parameter null");
192 _SI("Publish: %s, %d, %s, %#x, %s", dest, req_id, subject, error, data);
194 GVariant *param = g_variant_new("(isis)", req_id, subject, error, data);
195 IF_FAIL_VOID_TAG(param, _E, "Memory allocation failed");
198 g_dbus_connection_call(dbus_connection, dest, DBUS_PATH, DBUS_IFACE,
199 METHOD_RESPOND, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err);
203 static void handle_signal_received(GDBusConnection *conn, const gchar *sender,
204 const gchar *obj_path, const gchar *iface, const gchar *signal_name,
205 GVariant *param, gpointer user_data)
207 IF_FAIL_VOID_TAG(user_data, _W, "user_data cannot be null");
208 ctx::dbus_listener_iface *listener = static_cast<ctx::dbus_listener_iface*>(user_data);
209 listener->on_signal_received(sender, obj_path, iface, signal_name, param);
212 int64_t ctx::dbus_server_impl::signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, ctx::dbus_listener_iface* listener)
214 IF_FAIL_RETURN_TAG(dbus_connection, -1, _E, "Dbus not connected");
215 guint sid = g_dbus_connection_signal_subscribe(dbus_connection,
216 sender, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
217 handle_signal_received, listener, NULL);
218 return static_cast<int64_t>(sid);
221 void ctx::dbus_server_impl::signal_unsubscribe(int64_t subscription_id)
223 IF_FAIL_VOID_TAG(dbus_connection, _E, "Dbus not connected");
224 IF_FAIL_VOID_TAG(subscription_id >= 0, _W, "Invalid parameter");
225 g_dbus_connection_signal_unsubscribe(dbus_connection, static_cast<guint>(subscription_id));
228 void ctx::dbus_server::publish(const char* dest, int req_id, const char* subject, int error, const char* data)
230 _instance->publish(dest, req_id, subject, error, data);