1 /**************************************************************************
5 Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
7 Contact: Boram Park <boram1288.park@samsung.com>
8 Sangjin LEE <lsj119@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
39 #include <dbus/dbus.h>
44 #include "xdbg_types.h"
45 #include "xdbg_dbus_server.h"
48 #define REP_MSG_SIZE 8192
51 #define RECONNECT_TIME 1000
52 #define DISPATCH_TIME 50
54 typedef struct _XDbgDBusServerInfo
58 XDbgDbusServerMethod *methods;
63 static XDbgDBusServerInfo server_info;
65 static CARD32 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg);
66 static Bool _xDbgDBusServerInit (XDbgDBusServerInfo *info);
67 static void _xDbgDBusServerDeinit (XDbgDBusServerInfo *info);
70 _xDbgDBusServerReplyMessage (XDbgDBusServerInfo *info, DBusMessage *msg, char *reply)
72 DBusMessage *reply_msg = NULL;
75 XDBG_RETURN_VAL_IF_FAIL (info->conn != NULL, FALSE);
77 reply_msg = dbus_message_new_method_return (msg);
78 XDBG_RETURN_VAL_IF_FAIL (reply_msg != NULL, FALSE);
80 dbus_message_iter_init_append (reply_msg, &iter);
81 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reply))
83 XDBG_ERROR (MDBUS, "[SERVER] out of memory\n");
84 dbus_message_unref (reply_msg);
88 if (!dbus_connection_send (info->conn, reply_msg, NULL))
90 XDBG_ERROR (MDBUS, "[SERVER] failed: send reply\n");
91 dbus_message_unref (reply_msg);
95 XDBG_DEBUG (MDBUS, "[SERVER] send reply\n");
97 dbus_connection_flush (info->conn);
98 dbus_message_unref (reply_msg);
104 _xDbgDBusServerProcessMessage (XDbgDBusServerInfo *info, DBusMessage *msg)
106 XDbgDbusServerMethod **prev;
108 char err_buf[REP_MSG_SIZE] = {0,};
109 char *argv[ARGV_NUM] = {0,};
113 snprintf (err_buf, REP_MSG_SIZE, "error message!\n");
115 dbus_error_init (&err);
117 XDBG_DEBUG (MDBUS, "[SERVER] Process a message (%s.%s)\n",
118 dbus_message_get_interface (msg), dbus_message_get_member (msg));
120 XDBG_RETURN_IF_FAIL (info->conn != NULL);
122 for (prev = &info->methods; *prev; prev = &(*prev)->next)
124 XDbgDbusServerMethod *method = *prev;
126 if (!strcmp (dbus_message_get_member (msg), method->name))
128 DBusMessageIter iter;
129 char reply[REP_MSG_SIZE] = {0,};
133 if (!dbus_message_iter_init (msg, &iter))
135 XDBG_ERROR (MDBUS, "[SERVER] Message has no arguments!\n");
136 snprintf (err_buf, REP_MSG_SIZE, "Message has no arguments!\n");
144 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
146 XDBG_ERROR (MDBUS, "[SERVER] Argument is not string!\n");
147 snprintf (err_buf, REP_MSG_SIZE, "Argument is not string!\n");
151 dbus_message_iter_get_basic (&iter, &p);
155 XDBG_ERROR (MDBUS, "[SERVER] Can't get string!\n");
156 snprintf (err_buf, REP_MSG_SIZE, "Can't get string!\n");
160 argv[argc] = strdup (p);
162 } while (dbus_message_iter_has_next (&iter) &&
163 dbus_message_iter_next (&iter) &&
166 len = REP_MSG_SIZE - 1;
169 method->func (method->data, argc, argv, reply, &len);
171 _xDbgDBusServerReplyMessage (info, msg, reply);
173 for (i = 0; i < ARGV_NUM; i++)
176 dbus_error_free (&err);
185 _xDbgDBusServerReplyMessage (info, msg, err_buf);
187 for (i = 0; i < ARGV_NUM; i++)
190 dbus_error_free (&err);
194 _xDbgDBusServerWakeupHandler (pointer data, int error, pointer pRead)
196 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
198 if (!info || !info->conn || info->fd < 0)
201 if (FD_ISSET(info->fd, (fd_set*)pRead))
204 dbus_connection_read_write_dispatch (info->conn, 0);
205 } while (info->conn &&
206 dbus_connection_get_is_connected (info->conn) &&
207 dbus_connection_get_dispatch_status (info->conn) ==
208 DBUS_DISPATCH_DATA_REMAINS);
210 /* DON'T use info->conn from here. info->conn becomes NULL by
211 * dbus_connection_read_write_dispatch(_xDbgDBusServerMsgFilter)
216 static DBusHandlerResult
217 _xDbgDBusServerMsgHandler (DBusConnection *connection, DBusMessage *msg, void *data)
219 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
221 if (!info || !info->conn || !msg)
222 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
224 XDBG_DEBUG (MDBUS, "[SERVER] Got a message (%s.%s)\n",
225 dbus_message_get_interface (msg), dbus_message_get_member (msg));
227 if (!dbus_message_is_method_call (msg, XDBG_DBUS_INTERFACE, XDBG_DBUS_METHOD))
228 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
230 _xDbgDBusServerProcessMessage (info, msg);
232 return DBUS_HANDLER_RESULT_HANDLED;
235 static DBusHandlerResult
236 _xDbgDBusServerMsgFilter (DBusConnection *conn, DBusMessage *msg, void *data)
238 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
241 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
243 if (dbus_message_is_signal (msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
245 XDBG_DEBUG (MDBUS, "[SERVER] disconnected by signal\n");
246 _xDbgDBusServerDeinit (info);
249 TimerFree(info->timer);
250 info->timer = TimerSet(NULL, 0, 1, _xDbgDBusServerTimeout, info);
252 return DBUS_HANDLER_RESULT_HANDLED;
255 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
259 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg)
261 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)arg;
266 XDBG_DEBUG (MDBUS, "[SERVER] timeout\n");
268 if (_xDbgDBusServerInit (info))
270 TimerFree (info->timer);
275 return RECONNECT_TIME;
279 _xDbgDBusServerInit (XDbgDBusServerInfo *info)
281 DBusObjectPathVTable vtable = {.message_function = _xDbgDBusServerMsgHandler, };
285 dbus_error_init (&err);
287 XDBG_RETURN_VAL_IF_FAIL (info->conn == NULL, FALSE);
289 info->conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
290 if (dbus_error_is_set (&err))
292 XDBG_ERROR (MDBUS, "[SERVER] failed: connection (%s)\n", err.message);
297 XDBG_ERROR (MDBUS, "[SERVER] failed: connection NULL\n");
301 ret = dbus_bus_request_name (info->conn, XDBG_DBUS_SERVER,
302 DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
303 if (dbus_error_is_set (&err))
305 XDBG_ERROR (MDBUS, "[SERVER] failed: request name (%s)\n", err.message);
308 if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
310 XDBG_ERROR (MDBUS, "[SERVER] failed: Not Primary Owner (%d)\n", ret);
314 snprintf (info->rule, sizeof (info->rule), "type='method_call',interface='%s'",
315 XDBG_DBUS_INTERFACE);
317 /* blocks until we get a reply. */
318 dbus_bus_add_match (info->conn, info->rule, &err);
319 if (dbus_error_is_set (&err))
321 XDBG_ERROR (MDBUS, "[SERVER] failed: add match (%s)\n", err.message);
325 if (!dbus_connection_register_object_path (info->conn,
326 XDBG_DBUS_PATH, &vtable,
329 XDBG_ERROR (MDBUS, "[SERVER] failed: register object path\n");
333 dbus_connection_set_exit_on_disconnect (info->conn, FALSE);
335 if (!dbus_connection_add_filter (info->conn, _xDbgDBusServerMsgFilter, info, NULL))
337 XDBG_ERROR (MDBUS, "[SERVER] failed: add filter (%s)\n", err.message);
341 if (!dbus_connection_get_unix_fd (info->conn, &info->fd) || info->fd < 0)
343 XDBG_ERROR (MDBUS, "[SERVER] failed: get fd\n");
347 AddGeneralSocket (info->fd);
348 RegisterBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
349 _xDbgDBusServerWakeupHandler, info);
351 XDBG_INFO (MDBUS, "[SERVER] connected\n");
353 dbus_error_free (&err);
358 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
360 dbus_connection_unregister_object_path (info->conn, XDBG_DBUS_PATH);
362 dbus_bus_remove_match (info->conn, info->rule, &err);
363 dbus_error_free (&err);
365 dbus_bus_release_name (info->conn, XDBG_DBUS_SERVER, &err);
366 dbus_error_free (&err);
368 dbus_connection_close (info->conn);
370 dbus_error_free (&err);
378 _xDbgDBusServerDeinit (XDbgDBusServerInfo *info)
382 TimerFree (info->timer);
389 dbus_error_init (&err);
390 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
391 dbus_connection_unregister_object_path (info->conn, XDBG_DBUS_PATH);
392 dbus_bus_remove_match (info->conn, info->rule, &err);
393 dbus_error_free (&err);
394 dbus_bus_release_name (info->conn, XDBG_DBUS_SERVER, &err);
395 dbus_error_free (&err);
396 dbus_connection_unref (info->conn);
400 RemoveBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
401 _xDbgDBusServerWakeupHandler, info);
404 RemoveGeneralSocket (info->fd);
408 XDBG_INFO (MDBUS, "[SERVER] disconnected\n");
412 xDbgDBusServerConnect (void)
414 XDBG_DEBUG (MDBUS, "[SERVER] connecting\n");
416 memset (&server_info, 0, sizeof(server_info));
419 server_info.timer = TimerSet (NULL, 0, 1, _xDbgDBusServerTimeout, &server_info);
425 xDbgDBusServerDisconnect (void)
427 XDBG_DEBUG (MDBUS, "[SERVER] disconnecting\n");
429 _xDbgDBusServerDeinit (&server_info);
433 xDbgDBusServerAddMethod (XDbgDbusServerMethod *method)
435 XDbgDbusServerMethod **prev;
437 for (prev = &server_info.methods; *prev; prev = &(*prev)->next);
446 xDbgDBusServerRemoveMethod (XDbgDbusServerMethod *method)
448 XDbgDbusServerMethod **prev;
450 for (prev = &server_info.methods; *prev; prev = &(*prev)->next)
453 *prev = method->next;