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>
45 #include "xdbg_types.h"
46 #include "xdbg_dbus_server.h"
49 #define REP_MSG_SIZE 8192
52 #define RECONNECT_TIME 1000
53 #define DISPATCH_TIME 50
55 extern _X_EXPORT char *display;
57 typedef struct _XDbgDBusServerInfo
61 XDbgDbusServerMethod *methods;
64 char xdbg_dbus_server[STR_LEN];
65 char xdbg_dbus_path[STR_LEN];
68 static XDbgDBusServerInfo server_info;
70 static CARD32 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg);
71 static Bool _xDbgDBusServerInit (XDbgDBusServerInfo *info);
72 static void _xDbgDBusServerDeinit (XDbgDBusServerInfo *info);
75 _xdbgDBusServerGetClientPID(DBusConnection *conn, char *client_name)
77 DBusMessage *msg = NULL;
78 DBusMessage *reply_msg = NULL;
83 RETURN_VAL_IF_FAIL (client_name != NULL, 0);
85 dbus_error_init (&err);
87 msg = dbus_message_new_method_call ("org.freedesktop.DBus", "/org/freedesktop/DBus",
88 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
90 GOTO_IF_FAIL (msg != NULL, err_send);
92 dbus_message_iter_init_append (msg, &iter);
94 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &client_name))
96 XDBG_ERROR (MDBUS, "[SERVER] failed: append\n");
100 reply_msg = dbus_connection_send_with_reply_and_block (conn, msg,
103 if (dbus_error_is_set (&err))
105 XDBG_ERROR (MDBUS, "[SERVER] failed: send (%s)\n", err.message);
108 GOTO_IF_FAIL (reply_msg != NULL, err_send);
110 if (!dbus_message_iter_init (reply_msg, &iter))
112 XDBG_ERROR (MDBUS, "[SERVER] Message has no arguments\n");
116 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
118 XDBG_ERROR (MDBUS, "[SERVER] Argument is not unint32!\n");
122 dbus_message_iter_get_basic (&iter, &pid);
125 XDBG_ERROR (MDBUS, "[SERVER] pid is 0\n");
129 XDBG_DEBUG (MDBUS, "[SERVER] Get Client name:%s pid:%u\n", client_name, pid);
135 dbus_message_unref(msg);
137 dbus_message_unref(reply_msg);
144 _xDbgDBusServerCheckSmackLabel (DBusConnection *connection)
146 char xdbg_client_name[STR_LEN];
147 char label_path[STR_LEN];
153 snprintf(xdbg_client_name, sizeof(xdbg_client_name), "org.x.dbg.client%d", atoi(display));
155 pid = _xdbgDBusServerGetClientPID (connection, xdbg_client_name);
158 XDBG_ERROR (MDBUS, "[SERVER] failed: Get client PID\n");
162 snprintf(label_path, sizeof(label_path), "/proc/%u/attr/current", pid);
164 fd = open(label_path, O_RDONLY);
168 XDBG_ERROR (MDBUS, "[SERVER] Failed: Open client smack label path\n");
172 i = read(fd, label, sizeof(label));
177 XDBG_ERROR (MDBUS, "[SERVER] Failed: Read client smack label\n");
184 if (strcmp(label, "xorg"))
186 XDBG_ERROR (MDBUS, "[SERVER] Deny smack label:%s\n", label);
190 XDBG_DEBUG (MDBUS, "[SERVER] Get client smack label:%s\n", label);
196 _xDbgDBusServerReplyMessage (XDbgDBusServerInfo *info, DBusMessage *msg, char *reply)
198 DBusMessage *reply_msg = NULL;
199 DBusMessageIter iter;
201 XDBG_RETURN_VAL_IF_FAIL (info->conn != NULL, FALSE);
203 reply_msg = dbus_message_new_method_return (msg);
204 XDBG_RETURN_VAL_IF_FAIL (reply_msg != NULL, FALSE);
206 dbus_message_iter_init_append (reply_msg, &iter);
207 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reply))
209 XDBG_ERROR (MDBUS, "[SERVER] out of memory\n");
210 dbus_message_unref (reply_msg);
214 if (!dbus_connection_send (info->conn, reply_msg, NULL))
216 XDBG_ERROR (MDBUS, "[SERVER] failed: send reply\n");
217 dbus_message_unref (reply_msg);
221 XDBG_DEBUG (MDBUS, "[SERVER] send reply\n");
223 dbus_connection_flush (info->conn);
224 dbus_message_unref (reply_msg);
230 _xDbgDBusServerProcessMessage (XDbgDBusServerInfo *info, DBusMessage *msg)
232 XDbgDbusServerMethod **prev;
234 char err_buf[REP_MSG_SIZE] = {0,};
235 char *argv[ARGV_NUM] = {0,};
239 snprintf (err_buf, REP_MSG_SIZE, "error message!\n");
241 dbus_error_init (&err);
243 XDBG_DEBUG (MDBUS, "[SERVER] Process a message (%s.%s)\n",
244 dbus_message_get_interface (msg), dbus_message_get_member (msg));
246 XDBG_RETURN_IF_FAIL (info->conn != NULL);
248 for (prev = &info->methods; *prev; prev = &(*prev)->next)
250 XDbgDbusServerMethod *method = *prev;
252 if (!strcmp (dbus_message_get_member (msg), method->name))
254 DBusMessageIter iter;
255 char reply[REP_MSG_SIZE] = {0,};
259 if (!dbus_message_iter_init (msg, &iter))
261 XDBG_ERROR (MDBUS, "[SERVER] Message has no arguments!\n");
262 snprintf (err_buf, REP_MSG_SIZE, "Message has no arguments!\n");
270 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
272 XDBG_ERROR (MDBUS, "[SERVER] Argument is not string!\n");
273 snprintf (err_buf, REP_MSG_SIZE, "Argument is not string!\n");
277 dbus_message_iter_get_basic (&iter, &p);
281 XDBG_ERROR (MDBUS, "[SERVER] Can't get string!\n");
282 snprintf (err_buf, REP_MSG_SIZE, "Can't get string!\n");
286 argv[argc] = strdup (p);
288 } while (dbus_message_iter_has_next (&iter) &&
289 dbus_message_iter_next (&iter) &&
292 len = REP_MSG_SIZE - 1;
295 method->func (method->data, argc, argv, reply, &len);
297 _xDbgDBusServerReplyMessage (info, msg, reply);
299 for (i = 0; i < ARGV_NUM; i++)
302 dbus_error_free (&err);
311 _xDbgDBusServerReplyMessage (info, msg, err_buf);
313 for (i = 0; i < ARGV_NUM; i++)
316 dbus_error_free (&err);
320 _xDbgDBusServerWakeupHandler (pointer data, int error, pointer pRead)
322 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
324 if (!info || !info->conn || info->fd < 0)
327 if (FD_ISSET(info->fd, (fd_set*)pRead))
330 dbus_connection_read_write_dispatch (info->conn, 0);
331 } while (info->conn &&
332 dbus_connection_get_is_connected (info->conn) &&
333 dbus_connection_get_dispatch_status (info->conn) ==
334 DBUS_DISPATCH_DATA_REMAINS);
336 /* DON'T use info->conn from here. info->conn becomes NULL by
337 * dbus_connection_read_write_dispatch(_xDbgDBusServerMsgFilter)
342 static DBusHandlerResult
343 _xDbgDBusServerMsgHandler (DBusConnection *connection, DBusMessage *msg, void *data)
345 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
347 if (!info || !info->conn || !msg)
348 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
350 XDBG_DEBUG (MDBUS, "[SERVER] Got a message (%s.%s)\n",
351 dbus_message_get_interface (msg), dbus_message_get_member (msg));
353 if (!_xDbgDBusServerCheckSmackLabel(connection))
354 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
356 if (!dbus_message_is_method_call (msg, XDBG_DBUS_INTERFACE, XDBG_DBUS_METHOD))
357 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
359 _xDbgDBusServerProcessMessage (info, msg);
361 return DBUS_HANDLER_RESULT_HANDLED;
364 static DBusHandlerResult
365 _xDbgDBusServerMsgFilter (DBusConnection *conn, DBusMessage *msg, void *data)
367 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)data;
370 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
372 if (dbus_message_is_signal (msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
374 XDBG_DEBUG (MDBUS, "[SERVER] disconnected by signal\n");
375 _xDbgDBusServerDeinit (info);
378 TimerFree(info->timer);
379 info->timer = TimerSet(NULL, 0, 1, _xDbgDBusServerTimeout, info);
381 return DBUS_HANDLER_RESULT_HANDLED;
384 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
388 _xDbgDBusServerTimeout (OsTimerPtr timer, CARD32 time, pointer arg)
390 XDbgDBusServerInfo *info = (XDbgDBusServerInfo*)arg;
395 XDBG_DEBUG (MDBUS, "[SERVER] timeout\n");
397 if (_xDbgDBusServerInit (info))
399 TimerFree (info->timer);
404 return RECONNECT_TIME;
408 _xDbgDBusServerInit (XDbgDBusServerInfo *info)
410 DBusObjectPathVTable vtable = {.message_function = _xDbgDBusServerMsgHandler, };
414 dbus_error_init (&err);
416 XDBG_RETURN_VAL_IF_FAIL (info->conn == NULL, FALSE);
418 snprintf(info->xdbg_dbus_server, sizeof(info->xdbg_dbus_server), "org.x.dbg.server%d", atoi(display));
419 snprintf(info->xdbg_dbus_path, sizeof(info->xdbg_dbus_path), "/org/x/dbg/path/%d", atoi(display));
421 XDBG_DEBUG (MDBUS, "[SERVER] display number %d\n", atoi(display));
423 info->conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
424 if (dbus_error_is_set (&err))
426 XDBG_ERROR (MDBUS, "[SERVER] failed: connection (%s)\n", err.message);
431 XDBG_ERROR (MDBUS, "[SERVER] failed: connection NULL\n");
435 ret = dbus_bus_request_name (info->conn, info->xdbg_dbus_server,
436 DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
437 if (dbus_error_is_set (&err))
439 XDBG_ERROR (MDBUS, "[SERVER] failed: request name (%s)\n", err.message);
442 if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
444 XDBG_ERROR (MDBUS, "[SERVER] failed: Not Primary Owner (%d)\n", ret);
448 snprintf (info->rule, sizeof (info->rule), "type='method_call',interface='%s'",
449 XDBG_DBUS_INTERFACE);
451 /* blocks until we get a reply. */
452 dbus_bus_add_match (info->conn, info->rule, &err);
453 if (dbus_error_is_set (&err))
455 XDBG_ERROR (MDBUS, "[SERVER] failed: add match (%s)\n", err.message);
459 if (!dbus_connection_register_object_path (info->conn,
460 info->xdbg_dbus_path, &vtable,
463 XDBG_ERROR (MDBUS, "[SERVER] failed: register object path\n");
467 dbus_connection_set_exit_on_disconnect (info->conn, FALSE);
469 if (!dbus_connection_add_filter (info->conn, _xDbgDBusServerMsgFilter, info, NULL))
471 XDBG_ERROR (MDBUS, "[SERVER] failed: add filter (%s)\n", err.message);
475 if (!dbus_connection_get_unix_fd (info->conn, &info->fd) || info->fd < 0)
477 XDBG_ERROR (MDBUS, "[SERVER] failed: get fd\n");
481 AddGeneralSocket (info->fd);
482 RegisterBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
483 _xDbgDBusServerWakeupHandler, info);
485 XDBG_INFO (MDBUS, "[SERVER] connected\n");
487 dbus_error_free (&err);
492 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
494 dbus_connection_unregister_object_path (info->conn, info->xdbg_dbus_path);
496 dbus_bus_remove_match (info->conn, info->rule, &err);
497 dbus_error_free (&err);
499 dbus_bus_release_name (info->conn, info->xdbg_dbus_server, &err);
500 dbus_error_free (&err);
502 dbus_connection_close (info->conn);
504 dbus_error_free (&err);
512 _xDbgDBusServerDeinit (XDbgDBusServerInfo *info)
516 TimerFree (info->timer);
523 dbus_error_init (&err);
524 dbus_connection_remove_filter (info->conn, _xDbgDBusServerMsgFilter, info);
525 dbus_connection_unregister_object_path (info->conn, info->xdbg_dbus_path);
526 dbus_bus_remove_match (info->conn, info->rule, &err);
527 dbus_error_free (&err);
528 dbus_bus_release_name (info->conn, info->xdbg_dbus_server, &err);
529 dbus_error_free (&err);
530 dbus_connection_unref (info->conn);
534 RemoveBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
535 _xDbgDBusServerWakeupHandler, info);
538 RemoveGeneralSocket (info->fd);
542 XDBG_INFO (MDBUS, "[SERVER] disconnected\n");
546 xDbgDBusServerConnect (void)
548 XDBG_DEBUG (MDBUS, "[SERVER] connecting\n");
550 memset (&server_info, 0, sizeof(server_info));
553 server_info.timer = TimerSet (NULL, 0, 1, _xDbgDBusServerTimeout, &server_info);
559 xDbgDBusServerDisconnect (void)
561 XDBG_DEBUG (MDBUS, "[SERVER] disconnecting\n");
563 _xDbgDBusServerDeinit (&server_info);
567 xDbgDBusServerAddMethod (XDbgDbusServerMethod *method)
569 XDbgDbusServerMethod **prev;
571 for (prev = &server_info.methods; *prev; prev = &(*prev)->next);
580 xDbgDBusServerRemoveMethod (XDbgDbusServerMethod *method)
582 XDbgDbusServerMethod **prev;
584 for (prev = &server_info.methods; *prev; prev = &(*prev)->next)
587 *prev = method->next;