089e168cd72026107996bb9fd57726877cf2f538
[platform/core/uifw/wayland-tbm.git] / src / wayland-tbm-monitor-server.c
1 /*
2 Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.
3
4 Contact:
5       SooChan Lim <sc1.lim@samsung.com>,
6       Sangjin Lee <lsj119@samsung.com>,
7       Boram Park <boram1288.park@samsung.com>,
8       Changyeon Lee <cyeon.lee@samsung.com>
9       Roman Marchenko <r.marchenko@samsung.com>
10
11 Permission is hereby granted, free of charge, to any person obtaining a
12 copy of this software and associated documentation files (the "Software"),
13 to deal in the Software without restriction, including without limitation
14 the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 and/or sell copies of the Software, and to permit persons to whom the
16 Software is furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice (including the next
19 paragraph) shall be included in all copies or substantial portions of the
20 Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 */
30
31 #include "config.h"
32
33 #define _GNU_SOURCE
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stddef.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41
42 #include <sys/types.h>
43 #include <dirent.h>
44
45 #include <tbm_surface.h>
46 #include <tbm_surface_internal.h>
47 #include <wayland-server.h>
48
49 #include "wayland-tbm-server-protocol.h"
50
51 #include "wayland-tbm-int.h"
52 #include "wayland-tbm-server.h"
53
54 struct wayland_tbm_monitore_request {
55
56         struct wl_list link;
57
58         int id;
59
60         struct wayland_tbm_server *tbm_srv;
61         struct wl_client *wl_client;
62         struct wl_resource *wl_resource;
63         char app_name[256];
64         char cwd[WL_TBM_MONITOR_PATH_LEN];
65
66         char options[256]; /* raw options */
67         char arg_mem[256]; /* memory for argv */
68         char *argv[WL_TBM_MONITOR_ARGS_MAX];
69         int argc;
70
71         /* for responses */
72         char msg[WL_TBM_MONITOR_REPLY_MSG_LEN];
73         char *reply;
74         int len;
75
76         FILE *console;
77         struct wayland_tbm_monitor_path path;
78
79         int wait_count;
80 };
81
82 #define DEBUG_TRACE
83 #ifdef DEBUG_TRACE
84 #define WL_TBM_TRACE(fmt, ...)   if (bTrace) WL_TBM_S_LOG(fmt, ##__VA_ARGS__)
85 #else
86 #define WL_TBM_TRACE(fmt, ...)
87 #endif
88
89 static void _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r);
90
91 static int
92 _wayland_tbm_monitor_server_collect_files(FILE* f_to_collect, int need_remove)
93 {
94         char buf[1024*8];
95         int buf_len = 0;
96
97         DIR *dir_stream;
98         struct dirent *entry;
99         char * dir_name = "/tmp/";
100
101         int fd;
102
103         char *file_name = NULL;
104
105         dir_stream = opendir(dir_name);
106         if (!dir_stream) {
107                 WL_TBM_LOG("got an error trying to call 'opendir'.\n");
108                 return -1;
109         }
110
111         while ((entry = readdir(dir_stream))) {
112                 if (strncmp(entry->d_name, "tbm_debug_show_", strlen("tbm_debug_show_")))
113                         continue;
114
115                 int tmp = asprintf(&file_name, "%s/%s", dir_name, entry->d_name);
116                 if (tmp < 0)
117                         continue;
118
119                 fd = open(file_name, O_RDONLY);
120                 if (fd < 0) {
121                         WL_TBM_LOG(" got an error trying to open file");
122                         free(file_name);
123                         continue;
124                 }
125
126                 while ((buf_len = read(fd, buf, sizeof(buf))) > 0)
127                         fwrite(buf, buf_len, 1, f_to_collect);
128
129                 close(fd);
130
131                 if (need_remove)
132                         unlink(file_name);
133
134                 free(file_name);
135         }
136
137         closedir(dir_stream);
138
139         return 0;
140 }
141
142 void
143 _wayland_tbm_monitor_add_info_printf(struct wayland_tbm_monitore_request *r)
144 {
145         FILE *f;
146         if (r->path.file[0] != '\0') {
147                 if ((f = fopen(r->path.file, "a+")) != NULL) {
148                         _wayland_tbm_monitor_server_collect_files(f, r->path.console && r->console ? 0 : 1);
149                         fclose(f);
150                 }
151         }
152
153         if (r->path.console && r->console)
154                 _wayland_tbm_monitor_server_collect_files(r->console, 1);
155 }
156
157 static void
158 _wayland_tbm_monitor_request_printf(struct wayland_tbm_monitore_request *r, const char *fmt, ...)
159 {
160         FILE *f;
161         va_list arg;
162
163         va_start(arg, fmt);
164
165         if (r->path.file[0] != '\0') {
166                 if ((f = fopen(r->path.file, "a+")) != NULL) {
167                         vfprintf(f, fmt, arg);
168                         fclose(f);
169                 } else
170                         _wayland_tbm_monitor_request_printf(r, "server: can't write show to file: '%s'\n",
171                                                                                                 r->path.file);
172         }
173
174         if (r->path.console && r->console)
175                 vfprintf(r->console, fmt, arg);
176         va_end(arg);
177 }
178
179 static void
180 _wayland_tbm_monitor_request_delete(struct wayland_tbm_monitore_request *r)
181 {
182         WL_TBM_TRACE("request_id:%d\n", r->id);
183         wl_list_remove(&r->link);
184         if (r->console)
185                 fclose(r->console);
186         free(r);
187 }
188
189 static void
190 _wayland_tbm_monitor_request_unref(struct wayland_tbm_monitore_request *r)
191 {
192         r->wait_count--;
193         WL_TBM_TRACE("request_id:%d wait_count:%d\n", r->id, r->wait_count);
194         if (r->wait_count <= 0) {
195                 /* print additional info from clients */
196                 _wayland_tbm_monitor_add_info_printf(r);
197                 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
198                 _wayland_tbm_monitor_request_delete(r);
199         }
200 }
201
202 void
203 _send_request_to_client_with_wait(struct wayland_tbm_monitore_request *r,
204                                       struct wayland_tbm_monitor_target *target, int wait_answer)
205 {
206         pid_t c_pid, t_pid;
207         struct wl_resource *c_res_tmp = NULL;
208         struct wl_resource *c_res = NULL;
209         char request_id[32];
210         int i = 0;
211
212         snprintf(request_id, sizeof(request_id), "%d", r->id);
213
214         if (target->all) {      /* send option string to all clients */
215                 wl_resource_for_each(c_res, &r->tbm_srv->tbm_monitor_list) {
216                         if (c_res == r->wl_resource)
217                                 continue;
218 #ifdef  DEBUG_TRACE
219                         wl_client_get_credentials(wl_resource_get_client(c_res), &c_pid, NULL, NULL);
220                         WL_TBM_TRACE("send request:%d(%d) to client:%d option:'%s'\n", r->id, r->wait_count, c_pid, r->options);
221 #endif
222                         wl_tbm_monitor_send_request_to_client(c_res, r->options, request_id);
223                         if (wait_answer)
224                                 r->wait_count++;
225                 }
226         } else {
227                 while (target->pid[i]) {
228                         c_res = NULL;
229                         t_pid = target->pid[i++];
230                         /* find client and store into c_res */
231                         wl_resource_for_each(c_res_tmp, &r->tbm_srv->tbm_monitor_list) {
232                                 if (c_res_tmp == r->wl_resource)
233                                         continue;
234                                 wl_client_get_credentials(wl_resource_get_client(c_res_tmp), &c_pid, NULL, NULL);
235                                 if (t_pid == c_pid) {
236                                         c_res = c_res_tmp;
237                                         break;
238                                 }
239                         }
240
241                         /* send option string to c_res */
242                         if (c_res) {
243                                 WL_TBM_TRACE("send request:%d(%d) to client:%d option:'%s'\n", r->id, r->wait_count, t_pid, r->options);
244                                 wl_tbm_monitor_send_request_to_client(c_res, r->options, request_id);
245                                 if (wait_answer)
246                                         r->wait_count++;
247                         } else
248                                 _wayland_tbm_monitor_request_printf(r, "There isn't client with pid=%d\n", t_pid);
249                 }
250         }
251 }
252
253 static void
254 _waylend_tbm_monitor_server_list(struct wayland_tbm_monitore_request *r)
255 {
256         struct wl_resource *c_res = NULL;
257         struct wl_client *wl_client;
258         char app_name[256];
259         pid_t c_pid;
260         int i = 0;
261
262         _wayland_tbm_monitor_request_printf(r, "==================  app list  =======================\n");
263         _wayland_tbm_monitor_request_printf(r, "no pid  app_name\n");
264
265         if (!wl_list_empty(&r->tbm_srv->tbm_monitor_list)) {
266                 wl_resource_for_each(c_res, &r->tbm_srv->tbm_monitor_list) {
267
268                         wl_client = wl_resource_get_client(c_res);
269                         wl_client_get_credentials(wl_client, &c_pid, NULL, NULL);
270
271                         if (wl_client == r->wl_client)
272                                 continue;
273
274                         _wayland_tbm_util_get_appname_from_pid(c_pid, app_name);
275                         _wayland_tbm_util_get_appname_brief(app_name);
276
277                         _wayland_tbm_monitor_request_printf(r, "%-3d%-5d%s\n", ++i, c_pid, app_name);
278                 }
279         }
280
281         _wayland_tbm_monitor_request_printf(r, "======================================================\n");
282 }
283
284 static void
285 _waylend_tbm_monitor_server_show(struct wayland_tbm_monitore_request *r)
286 {
287         struct wayland_tbm_monitor_target target = {0};
288
289         if (!_waylend_tbm_util_target_parse(r->argv[1], &target)) {
290                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target for -show\n", r->argv[1]);
291                 return;
292         }
293
294         if (r->argv[2]) {
295                 r->path.console = r->path.dlog = r->path.file[0] = 0;
296                 if (!_wayland_tbm_util_show_path_parse(r->argv[2], r->cwd, &r->path)) {
297                         r->path.console = 1;
298                         _wayland_tbm_monitor_request_printf(r, "'%s' - unknown path for -show\n", r->argv[2]);
299                         return;
300                 }
301         }
302
303         if (target.server) {
304                 if (r->path.dlog)
305                         tbm_bufmgr_debug_show(r->tbm_srv->bufmgr);
306                 else {
307                         char *show_str;
308
309                         show_str = tbm_bufmgr_debug_tbm_info_get(r->tbm_srv->bufmgr);
310                         WL_TBM_RETURN_IF_FAIL(show_str);
311
312                         if (r->path.console && r->console)
313                                 fprintf(r->console, "%s", show_str);
314
315                         if (r->path.file[0] != '\0') {
316                                 FILE *f = NULL;
317
318                                 if ((f = fopen(r->path.file, "a+")) != NULL) {
319                                         fprintf(f, "%s", show_str);
320                                         fclose(f);
321                                 } else
322                                         _wayland_tbm_monitor_request_printf(r,
323                                                 "server: can't write show to file: '%s'\n",
324                                                 r->path.file);
325                         }
326
327                         free(show_str);
328                 }
329         }
330
331         _send_request_to_client_with_wait(r, &target, 1);
332 }
333
334 static void
335 _waylend_tbm_monitor_server_trace(struct wayland_tbm_monitore_request *r)
336 {
337
338         struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
339         WL_TBM_MONITOR_PROC_STATE cmd;
340         int st;
341
342         cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
343
344         if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
345                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -trace\n", r->argv[1]);
346                 _wayland_tbm_monitor_server_usage(r);
347                 return;
348         }
349
350         if (!_waylend_tbm_util_target_parse(r->argv[2], &target)) {
351                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target for -trace\n", r->argv[2]);
352                 return;
353         }
354
355         if (target.server) {
356                 st = _waylend_tbm_util_trace(cmd, r->tbm_srv->bufmgr);
357                 _wayland_tbm_monitor_request_printf(r, "server: trace state: %s\n", st ? "on" : "off");
358         }
359
360         _send_request_to_client_with_wait(r, &target, 1);
361 }
362
363 static void
364 _waylend_tbm_monitor_server_dump_snapshot(struct wayland_tbm_monitore_request *r)
365 {
366         struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
367         double scale = 0;
368         int i;
369
370         for (i = 1; i < r->argc; i++) {
371                 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
372                         continue;
373                 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
374                         continue;
375
376                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_snapshot\n", r->argv[2]);
377                 _wayland_tbm_monitor_server_usage(r);
378                 return;
379         }
380
381         if (target.server) {
382                 _waylend_tbm_util_dump_snapshot(r->tbm_srv->bufmgr, scale);
383                 _wayland_tbm_monitor_request_printf(r, "server: snapshot dump is done\n");
384         }
385         _send_request_to_client_with_wait(r, &target, 1);
386 }
387
388 static void
389 _waylend_tbm_monitor_server_dump_queue(struct wayland_tbm_monitore_request *r)
390 {
391         struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
392         WL_TBM_MONITOR_PROC_STATE cmd;
393         double scale = 0;
394         int st = 0;
395         int i;
396
397         cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
398         if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
399                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -dump_queue\n", r->argv[1]);
400                 _wayland_tbm_monitor_server_usage(r);
401                 return;
402         }
403
404         for (i = 2; i < r->argc; i++) {
405                 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
406                         continue;
407                 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
408                         continue;
409
410                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_queue\n", r->argv[2]);
411                 _wayland_tbm_monitor_server_usage(r);
412                 return;
413         }
414
415         if (target.server) {
416                 st = _waylend_tbm_util_dump_queue(cmd, r->tbm_srv->bufmgr, scale);
417                 _wayland_tbm_monitor_request_printf(r, "server: queue dump state: %s\n", st ? "on" : "off");
418         }
419         _send_request_to_client_with_wait(r, &target, 1);
420 }
421
422 static struct {
423         const char *opt;
424         void (*func)(struct wayland_tbm_monitore_request *r);
425         const char *desc;
426         const char *arg;
427         const char *ex;
428 } option_proc[] = {
429         {
430                 "list",
431                 _waylend_tbm_monitor_server_list,
432                 "get list of tbm clients",
433                 NULL, /*args*/
434                 NULL, /*example*/
435         },
436         {
437                 "show",
438                 _waylend_tbm_monitor_server_show,
439                 "print all tbm_bo information for (all | server,<pid>,... ) to path (console | dlog | <filepath>)"
440                 ,
441                 "<target> [<path>]\n"
442                 "\t\t""  <target>\n"
443                 "\t\t""    all                 - clients and server\n"
444                 "\t\t""    server,<pid>,...    - list of targets\n"
445                 ,
446                 "1,2,server dlog,console; server tmp.txt; all"
447         },
448         {
449                 "trace",
450                 _waylend_tbm_monitor_server_trace,
451                 "trace the changes or the information of the tbm_bo (command: on | off | status)"
452                 ,
453                 "<cmd> [<target>]\n"
454                 "\t\t""    on | off            - turn on/off the trace\n"
455                 "\t\t""    status              - show status of all targets\n"
456                 "\t\t""  <target>\n"
457                 "\t\t""    all                 - clients and server(by default)\n"
458                 "\t\t""    server,<pid>,...    - list of targets\n"
459                 ,
460                 "on server,1,2; off;"
461         },
462         {
463                 "dump_snapshot",
464                 _waylend_tbm_monitor_server_dump_snapshot,
465                 "make dumps of all tbm_surfaces for (all | server,<pid>,... ) with scale"
466                 ,
467                 ""
468                 ,
469                 "all scale=0.5; server,1,2 scale=0.5"
470         },
471         {
472                 "dump_queue",
473                 _waylend_tbm_monitor_server_dump_queue,
474                 "make dumps for the tbm_surfaces which are queued with scale"
475                 ,
476                 "<cmd> [<target>] [<scale>]\n"
477                 "\t\t""  <cmd>\n"
478                 "\t\t""    on                  - turn on the dump with scale\n"
479                 "\t\t""    off                 - turn off the dump\n"
480                 "\t\t""    status              - show status of all targets\n"
481                 "\t\t""  <target>\n"
482                 "\t\t""    all                 - clients and server(by default)\n"
483                 "\t\t""    server,<pid>,...    - list of targets\n"
484                 ,
485                 "on scale=0.5; off"
486         }
487 };
488
489 static void
490 _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r)
491 {
492         int opt_size = sizeof(option_proc) / sizeof(option_proc[0]);
493         int i;
494
495         _wayland_tbm_monitor_request_printf(r, "usage: %s \n\n", r->app_name);
496
497         for (i = 0; i < opt_size; i++) {
498
499                 _wayland_tbm_monitor_request_printf(r, "\t-%s\t%s\n", option_proc[i].opt, option_proc[i].desc);
500                 if (option_proc[i].arg)
501                         _wayland_tbm_monitor_request_printf(r, "\t\t  %s\n", option_proc[i].arg);
502                 if (option_proc[i].ex)
503                         _wayland_tbm_monitor_request_printf(r, "\t\t  ex) %s\n", option_proc[i].ex);
504                 _wayland_tbm_monitor_request_printf(r, "\n");
505         }
506 }
507
508 static struct wayland_tbm_monitore_request *
509 _wayland_tbm_monitor_request_create(struct wl_client *client,
510                                             struct wl_resource *resource, const char *options)
511 {
512         char *end = NULL;
513         char path[256];
514         int i;
515         int pid;
516         static int id_count = 1;
517
518         struct wayland_tbm_monitore_request *r = calloc(1, sizeof(struct wayland_tbm_monitore_request));
519         memset(r, 0 , sizeof(struct wayland_tbm_monitore_request));
520
521         struct wayland_tbm_server *tbm_srv =
522                         (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
523
524         /* copy options to a local memory */
525         snprintf(r->options, sizeof(r->options), "%s", options);
526         snprintf(r->arg_mem, sizeof(r->arg_mem), "%s", options);
527
528         r->wl_client = client;
529         r->wl_resource = resource;
530         r->reply = r->msg;
531         r->len = WL_TBM_MONITOR_REPLY_MSG_LEN;
532         r->tbm_srv = tbm_srv;
533         r->id = id_count++;
534         r->path.console = 1;
535         wl_list_init(&r->link);
536
537         /* get pid */
538         wl_client_get_credentials(r->wl_client, &pid, NULL, NULL);
539         _wayland_tbm_util_get_appname_from_pid(pid, r->app_name);
540         _wayland_tbm_util_get_appname_brief(r->app_name);
541
542         /* get access to the console of a wayland-tbm-monitor application */
543         snprintf(path, sizeof(path), "/proc/%d/fd/1", pid);
544         r->console = fopen(path, "a");
545         if (!r->console) {
546                 _wayland_tbm_monitor_request_printf(r, "Can't get access to the console\n");
547                 return r;
548         }
549
550         /* get cwd of the client */
551         snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
552         if (readlink(path, r->cwd, sizeof(r->cwd)) < 0) {
553                 _wayland_tbm_monitor_request_printf(r, "Can't get cwd\n");
554                 return r;
555         }
556
557         /* parse options */
558         r->argv[r->argc] = strtok_r(r->arg_mem, " ", &end);
559         while (r->argv[r->argc]) {
560                 r->argc++;
561                 if (r->argc == WL_TBM_MONITOR_ARGS_MAX) {
562                         _wayland_tbm_monitor_request_printf(r, "Too many arguments\n");
563                         r->argc = 0;
564                         break;
565                 }
566                 r->argv[r->argc] = strtok_r(NULL, " ", &end);
567         }
568
569         WL_TBM_TRACE("request_id:%d option:'%s' argc:%d [%s %s %s] \n", r->id, r->options, r->argc, r->argv[0], r->argv[1], r->argv[2]);
570
571         /* execute */
572         if (r->argc > 0) {
573                 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
574                         if (r->argv[0][0] == '-' && !strncmp(r->argv[0] + 1, option_proc[i].opt, 32)) {
575                                 if (option_proc[i].func) {
576                                         wl_list_insert(&tbm_srv->tbm_monitor_request_list, &r->link);
577                                         option_proc[i].func(r);
578                                 } else {
579                                         _wayland_tbm_monitor_request_printf(r, "'%s' not implemented\n", r->argv[0]);
580                                 }
581                                 return r;
582                         }
583                 }
584         }
585
586
587         _wayland_tbm_monitor_request_printf(r, "'%s' is unknown options\n", r->argv[0]);
588         _wayland_tbm_monitor_server_usage(r);
589         return r;
590
591 }
592
593 struct wayland_tbm_monitore_request *
594 _wayland_tbm_monitor_get_request_by_id(struct wayland_tbm_server *tbm_srv, const char *id_str)
595 {
596         struct wayland_tbm_monitore_request *r = NULL;
597         unsigned int id = 0;
598
599         if (sscanf(id_str, "%d", &id) != 1)
600                 return NULL;
601
602         wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
603                 if (r->id == id)
604                         return r;
605
606         return NULL;
607 }
608
609 struct wayland_tbm_monitore_request *
610 _wayland_tbm_monitor_get_request_by_resource(struct wayland_tbm_server *tbm_srv,
611                                                                                          struct wl_resource *resource)
612 {
613         struct wayland_tbm_monitore_request *r = NULL;
614         wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
615                 if (r->wl_resource == resource)
616                         return r;
617
618         return NULL;
619 }
620
621 static void
622 _wayland_tbm_monitor_impl_responce_to_server(struct wl_client *client,
623                                                                                          struct wl_resource *resource,
624                                                                                          const char *message, const char *request_id)
625 {
626         struct wayland_tbm_monitore_request *r = NULL;
627         struct wayland_tbm_server *tbm_srv = NULL;
628
629         tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
630         r = _wayland_tbm_monitor_get_request_by_id(tbm_srv, request_id);
631         if (r == NULL)
632                 return;
633
634         _wayland_tbm_monitor_request_printf(r, "%s", message);
635         _wayland_tbm_monitor_request_unref(r);
636 }
637
638 static void
639 _wayland_tbm_monitor_impl_request_to_sever(struct wl_client *client,
640                                                                                    struct wl_resource *resource,
641                                                                                    const char *options)
642 {
643         struct wayland_tbm_monitore_request *r  = NULL;
644         uid_t uid = 0;
645
646         wl_client_get_credentials(client, NULL, &uid, NULL);
647         if (uid != 0) {
648                 wl_tbm_monitor_send_done(resource, "wayland-tbm-monitor: SHOULD be a superuser.\n");
649                 return;
650         }
651
652         r = _wayland_tbm_monitor_request_create(client, resource, options);
653         if (r->wait_count == 0) {
654                 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
655                 _wayland_tbm_monitor_request_delete(r);
656         }
657 }
658
659 static void
660 _wayland_tbm_monitor_impl_destroy(struct wl_client *client,
661                                         struct wl_resource *wl_tbm_monitor)
662 {
663 #ifdef DEBUG_TRACE
664         pid_t pid;
665
666         wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
667         WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
668 #endif
669
670         wl_resource_destroy(wl_tbm_monitor);
671 }
672
673 static void
674 _wayland_tbm_monitor_destroy_resource(struct wl_resource *wl_tbm_monitor)
675 {
676         struct wayland_tbm_monitore_request *r = NULL;
677         struct wayland_tbm_server *tbm_srv = NULL;
678
679 #ifdef DEBUG_TRACE
680         pid_t pid;
681
682         wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
683         WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
684 #endif
685
686         /* delete all requests from this client */
687         tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(wl_tbm_monitor);
688         while ((r = _wayland_tbm_monitor_get_request_by_resource(tbm_srv, wl_tbm_monitor)) != NULL)
689                 _wayland_tbm_monitor_request_delete(r);
690
691         wl_list_remove(wl_resource_get_link(wl_tbm_monitor));
692 }
693
694 static const struct wl_tbm_monitor_interface _wayland_tbm_monitor_implementation = {
695         _wayland_tbm_monitor_impl_destroy,
696         _wayland_tbm_monitor_impl_request_to_sever,
697         _wayland_tbm_monitor_impl_responce_to_server,
698 };
699
700 static void
701 _wayland_tbm_monitor_bind_cb(struct wl_client *client, void *data,
702                             uint32_t version, uint32_t id)
703 {
704         struct wayland_tbm_server *tbm_srv = (struct wayland_tbm_server*)data;
705         struct wl_resource *wl_tbm_monitor;
706
707         wl_tbm_monitor = wl_resource_create(client, &wl_tbm_monitor_interface, 2, id);
708         if (!wl_tbm_monitor) {
709                 wl_client_post_no_memory(client);
710                 return;
711         }
712
713         wl_resource_set_implementation(wl_tbm_monitor,
714                                                                    &_wayland_tbm_monitor_implementation,
715                                                                    tbm_srv,
716                                                                    _wayland_tbm_monitor_destroy_resource);
717         wl_list_insert(&tbm_srv->tbm_monitor_list, wl_resource_get_link(wl_tbm_monitor));
718
719 #ifdef DEBUG_TRACE
720         pid_t pid;
721
722         wl_client_get_credentials(client, &pid, NULL, NULL);
723         WL_TBM_TRACE("wl_tbm_monitor bind. client=%d\n", pid);
724 #endif
725 }
726
727 int wayland_tbm_monitor_server_init(struct wayland_tbm_server *tbm_srv)
728 {
729         tbm_srv->wl_tbm_monitor_global = wl_global_create(tbm_srv->display,
730                                         &wl_tbm_monitor_interface, 1, tbm_srv,
731                                         _wayland_tbm_monitor_bind_cb);
732         WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv->wl_tbm_monitor_global, 0);
733         wl_list_init(&tbm_srv->tbm_monitor_list);
734         wl_list_init(&tbm_srv->tbm_monitor_request_list);
735         return 1;
736 }