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 extern _X_EXPORT char *display;
56 typedef struct _XDbgDBusServerInfo
60 XDbgDbusServerMethod *methods;
63 char xdbg_dbus_server[STR_LEN];
64 char xdbg_dbus_path[STR_LEN];
67 static XDbgDBusServerInfo server_info;
69 static CARD32 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg);
70 static Bool _xDbgDBusServerInit (XDbgDBusServerInfo *info);
71 static void _xDbgDBusServerDeinit (XDbgDBusServerInfo *info);
74 _xDbgDBusServerReplyMessage (XDbgDBusServerInfo *info, DBusMessage *msg, char *reply)
76 DBusMessage *reply_msg = NULL;
79 XDBG_RETURN_VAL_IF_FAIL (info->conn != NULL, FALSE);
81 reply_msg = dbus_message_new_method_return (msg);
82 XDBG_RETURN_VAL_IF_FAIL (reply_msg != NULL, FALSE);
84 dbus_message_iter_init_append (reply_msg, &iter);
85 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reply))
87 XDBG_ERROR (MDBUS, "[SERVER] out of memory\n");
88 dbus_message_unref (reply_msg);
92 if (!dbus_connection_send (info->conn, reply_msg, NULL))
94 XDBG_ERROR (MDBUS, "[SERVER] failed: send reply\n");
95 dbus_message_unref (reply_msg);
99 XDBG_DEBUG (MDBUS, "[SERVER] send reply\n");
101 dbus_connection_flush (info->conn);
102 dbus_message_unref (reply_msg);
108 _xDbgDBusServerProcessMessage (XDbgDBusServerInfo *info, DBusMessage *msg)
110 XDbgDbusServerMethod **prev;
112 char err_buf[REP_MSG_SIZE] = {0,};
113 char *argv[ARGV_NUM] = {0,};
117 snprintf (err_buf, REP_MSG_SIZE, "error message!\n");
119 dbus_error_init (&err);
121 XDBG_DEBUG (MDBUS, "[SERVER] Process a message (%s.%s)\n",
122 dbus_message_get_interface (msg), dbus_message_get_member (msg));
124 XDBG_RETURN_IF_FAIL (info->conn != NULL);
126 for (prev = &info->methods; *prev; prev = &(*prev)->next)
128 XDbgDbusServerMethod *method = *prev;
130 if (!strcmp (dbus_message_get_member (msg), method->name))
132 DBusMessageIter iter;
133 char reply[REP_MSG_SIZE] = {0,};
137 if (!dbus_message_iter_init (msg, &iter))
139 XDBG_ERROR (MDBUS, "[SERVER] Message has no arguments!\n");
140 snprintf (err_buf, REP_MSG_SIZE, "Message has no arguments!\n");
148 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
150 XDBG_ERROR (MDBUS, "[SERVER] Argument is not string!\n");
151 snprintf (err_buf, REP_MSG_SIZE, "Argument is not string!\n");
155 dbus_message_iter_get_basic (&iter, &p);
159 XDBG_ERROR (MDBUS, "[SERVER] Can't get string!\n");
160 snprintf (err_buf, REP_MSG_SIZE, "Can't get string!\n");
164 argv[argc] = strdup (p);
166 } while (dbus_message_iter_has_next (&iter) &&
167 dbus_message_iter_next (&iter) &&
170 len = REP_MSG_SIZE - 1;
173 method->func (method->data, argc, argv, reply, &len);
175 _xDbgDBusServerReplyMessage (info, msg, reply);
177 for (i = 0; i < ARGV_NUM; i++)
180 dbus_error_free (&err);
189 _xDbgDBusServerReplyMessage (info, msg, err_buf);
191 for (i = 0; i < ARGV_NUM; i++)
194 dbus_error_free (&err);
198 _xDbgDBusServerWakeupHandler (pointer data, int error, pointer pRead)
200 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
202 if (!info || !info->conn || info->fd < 0)
205 if (FD_ISSET(info->fd, (fd_set*)pRead))
208 dbus_connection_read_write_dispatch (info->conn, 0);
209 } while (info->conn &&
210 dbus_connection_get_is_connected (info->conn) &&
211 dbus_connection_get_dispatch_status (info->conn) ==
212 DBUS_DISPATCH_DATA_REMAINS);
214 /* DON'T use info->conn from here. info->conn becomes NULL by
215 * dbus_connection_read_write_dispatch(_xDbgDBusServerMsgFilter)
220 static DBusHandlerResult
221 _xDbgDBusServerMsgHandler (DBusConnection *connection, DBusMessage *msg, void *data)
223 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
225 if (!info || !info->conn || !msg)
226 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
228 XDBG_DEBUG (MDBUS, "[SERVER] Got a message (%s.%s)\n",
229 dbus_message_get_interface (msg), dbus_message_get_member (msg));
231 if (!dbus_message_is_method_call (msg, XDBG_DBUS_INTERFACE, XDBG_DBUS_METHOD))
232 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
234 _xDbgDBusServerProcessMessage (info, msg);
236 return DBUS_HANDLER_RESULT_HANDLED;
239 static DBusHandlerResult
240 _xDbgDBusServerMsgFilter (DBusConnection *conn, DBusMessage *msg, void *data)
242 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
245 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
247 if (dbus_message_is_signal (msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
249 XDBG_DEBUG (MDBUS, "[SERVER] disconnected by signal\n");
250 _xDbgDBusServerDeinit (info);
253 TimerFree(info->timer);
254 info->timer = TimerSet(NULL, 0, 1, _xDbgDBusServerTimeout, info);
256 return DBUS_HANDLER_RESULT_HANDLED;
259 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
263 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg)
265 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)arg;
270 XDBG_DEBUG (MDBUS, "[SERVER] timeout\n");
272 if (_xDbgDBusServerInit (info))
274 TimerFree (info->timer);
279 return RECONNECT_TIME;
283 _xDbgDBusServerInit (XDbgDBusServerInfo *info)
285 DBusObjectPathVTable vtable = {.message_function = _xDbgDBusServerMsgHandler, };
289 dbus_error_init (&err);
291 XDBG_RETURN_VAL_IF_FAIL (info->conn == NULL, FALSE);
293 snprintf(info->xdbg_dbus_server, sizeof(info->xdbg_dbus_server), "org.x.dbg.server%d", atoi(display));
294 snprintf(info->xdbg_dbus_path, sizeof(info->xdbg_dbus_path), "/org/x/dbg/path/%d", atoi(display));
296 XDBG_DEBUG (MDBUS, "[SERVER] display number %d\n", atoi(display));
298 info->conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
299 if (dbus_error_is_set (&err))
301 XDBG_ERROR (MDBUS, "[SERVER] failed: connection (%s)\n", err.message);
306 XDBG_ERROR (MDBUS, "[SERVER] failed: connection NULL\n");
310 ret = dbus_bus_request_name (info->conn, info->xdbg_dbus_server,
311 DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
312 if (dbus_error_is_set (&err))
314 XDBG_ERROR (MDBUS, "[SERVER] failed: request name (%s)\n", err.message);
317 if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
319 XDBG_ERROR (MDBUS, "[SERVER] failed: Not Primary Owner (%d)\n", ret);
323 snprintf (info->rule, sizeof (info->rule), "type='method_call',interface='%s'",
324 XDBG_DBUS_INTERFACE);
326 /* blocks until we get a reply. */
327 dbus_bus_add_match (info->conn, info->rule, &err);
328 if (dbus_error_is_set (&err))
330 XDBG_ERROR (MDBUS, "[SERVER] failed: add match (%s)\n", err.message);
334 if (!dbus_connection_register_object_path (info->conn,
335 info->xdbg_dbus_path, &vtable,
338 XDBG_ERROR (MDBUS, "[SERVER] failed: register object path\n");
342 dbus_connection_set_exit_on_disconnect (info->conn, FALSE);
344 if (!dbus_connection_add_filter (info->conn, _xDbgDBusServerMsgFilter, info, NULL))
346 XDBG_ERROR (MDBUS, "[SERVER] failed: add filter (%s)\n", err.message);
350 if (!dbus_connection_get_unix_fd (info->conn, &info->fd) || info->fd < 0)
352 XDBG_ERROR (MDBUS, "[SERVER] failed: get fd\n");
356 AddGeneralSocket (info->fd);
357 RegisterBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
358 _xDbgDBusServerWakeupHandler, info);
360 XDBG_INFO (MDBUS, "[SERVER] connected\n");
362 dbus_error_free (&err);
367 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
369 dbus_connection_unregister_object_path (info->conn, info->xdbg_dbus_path);
371 dbus_bus_remove_match (info->conn, info->rule, &err);
372 dbus_error_free (&err);
374 dbus_bus_release_name (info->conn, info->xdbg_dbus_server, &err);
375 dbus_error_free (&err);
377 dbus_connection_close (info->conn);
379 dbus_error_free (&err);
387 _xDbgDBusServerDeinit (XDbgDBusServerInfo *info)
391 TimerFree (info->timer);
398 dbus_error_init (&err);
399 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
400 dbus_connection_unregister_object_path (info->conn, info->xdbg_dbus_path);
401 dbus_bus_remove_match (info->conn, info->rule, &err);
402 dbus_error_free (&err);
403 dbus_bus_release_name (info->conn, info->xdbg_dbus_server, &err);
404 dbus_error_free (&err);
405 dbus_connection_unref (info->conn);
409 RemoveBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
410 _xDbgDBusServerWakeupHandler, info);
413 RemoveGeneralSocket (info->fd);
417 XDBG_INFO (MDBUS, "[SERVER] disconnected\n");
421 xDbgDBusServerConnect (void)
423 XDBG_DEBUG (MDBUS, "[SERVER] connecting\n");
425 memset (&server_info, 0, sizeof(server_info));
428 server_info.timer = TimerSet (NULL, 0, 1, _xDbgDBusServerTimeout, &server_info);
434 xDbgDBusServerDisconnect (void)
436 XDBG_DEBUG (MDBUS, "[SERVER] disconnecting\n");
438 _xDbgDBusServerDeinit (&server_info);
442 xDbgDBusServerAddMethod (XDbgDbusServerMethod *method)
444 XDbgDbusServerMethod **prev;
446 for (prev = &server_info.methods; *prev; prev = &(*prev)->next);
455 xDbgDBusServerRemoveMethod (XDbgDbusServerMethod *method)
457 XDbgDbusServerMethod **prev;
459 for (prev = &server_info.methods; *prev; prev = &(*prev)->next)
462 *prev = method->next;