show the dump path on the console.
[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         char *path = NULL;
370
371         for (i = 1; i < r->argc; i++) {
372                 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
373                         continue;
374                 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
375                         continue;
376
377                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_snapshot\n", r->argv[2]);
378                 _wayland_tbm_monitor_server_usage(r);
379                 return;
380         }
381
382         if (target.server) {
383                 path = _wayland_tbm_dump_directory_make();
384                 _waylend_tbm_util_dump_snapshot(r->tbm_srv->bufmgr, scale, path);
385                 _wayland_tbm_monitor_request_printf(r, "server: snapshot dump is done. path=%s\n", path);
386                 free(path);
387         }
388         _send_request_to_client_with_wait(r, &target, 1);
389 }
390
391 static void
392 _waylend_tbm_monitor_server_dump_queue(struct wayland_tbm_monitore_request *r)
393 {
394         struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
395         WL_TBM_MONITOR_PROC_STATE cmd;
396         double scale = 0;
397         int st = 0;
398         int i;
399
400         cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
401         if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
402                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -dump_queue\n", r->argv[1]);
403                 _wayland_tbm_monitor_server_usage(r);
404                 return;
405         }
406
407         for (i = 2; i < r->argc; i++) {
408                 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
409                         continue;
410                 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
411                         continue;
412
413                 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_queue\n", r->argv[2]);
414                 _wayland_tbm_monitor_server_usage(r);
415                 return;
416         }
417
418         if (target.server) {
419                 st = _waylend_tbm_util_dump_queue(cmd, r->tbm_srv->bufmgr, scale);
420                 _wayland_tbm_monitor_request_printf(r, "server: queue dump state: %s\n", st ? "on" : "off");
421         }
422         _send_request_to_client_with_wait(r, &target, 1);
423 }
424
425 static struct {
426         const char *opt;
427         void (*func)(struct wayland_tbm_monitore_request *r);
428         const char *desc;
429         const char *arg;
430         const char *ex;
431 } option_proc[] = {
432         {
433                 "list",
434                 _waylend_tbm_monitor_server_list,
435                 "get list of tbm clients",
436                 NULL, /*args*/
437                 NULL, /*example*/
438         },
439         {
440                 "show",
441                 _waylend_tbm_monitor_server_show,
442                 "print all tbm_bo information for (all | server,<pid>,... ) to path (console | dlog | <filepath>)"
443                 ,
444                 "<target> [<path>]\n"
445                 "\t\t""  <target>\n"
446                 "\t\t""    all                 - clients and server\n"
447                 "\t\t""    server,<pid>,...    - list of targets\n"
448                 ,
449                 "1,2,server dlog,console; server tmp.txt; all"
450         },
451         {
452                 "trace",
453                 _waylend_tbm_monitor_server_trace,
454                 "trace the changes or the information of the tbm_bo (command: on | off | status)"
455                 ,
456                 "<cmd> [<target>]\n"
457                 "\t\t""    on | off            - turn on/off the trace\n"
458                 "\t\t""    status              - show status of all targets\n"
459                 "\t\t""  <target>\n"
460                 "\t\t""    all                 - clients and server(by default)\n"
461                 "\t\t""    server,<pid>,...    - list of targets\n"
462                 ,
463                 "on server,1,2; off;"
464         },
465         {
466                 "dump_snapshot",
467                 _waylend_tbm_monitor_server_dump_snapshot,
468                 "make dumps of all tbm_surfaces for (all | server,<pid>,... ) with scale"
469                 ,
470                 ""
471                 ,
472                 "all scale=0.5; server,1,2 scale=0.5"
473         },
474         {
475                 "dump_queue",
476                 _waylend_tbm_monitor_server_dump_queue,
477                 "make dumps for the tbm_surfaces which are queued with scale"
478                 ,
479                 "<cmd> [<target>] [<scale>]\n"
480                 "\t\t""  <cmd>\n"
481                 "\t\t""    on                  - turn on the dump with scale\n"
482                 "\t\t""    off                 - turn off the dump\n"
483                 "\t\t""    status              - show status of all targets\n"
484                 "\t\t""  <target>\n"
485                 "\t\t""    all                 - clients and server(by default)\n"
486                 "\t\t""    server,<pid>,...    - list of targets\n"
487                 ,
488                 "on scale=0.5; off"
489         }
490 };
491
492 static void
493 _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r)
494 {
495         int opt_size = sizeof(option_proc) / sizeof(option_proc[0]);
496         int i;
497
498         _wayland_tbm_monitor_request_printf(r, "usage: %s \n\n", r->app_name);
499
500         for (i = 0; i < opt_size; i++) {
501
502                 _wayland_tbm_monitor_request_printf(r, "\t-%s\t%s\n", option_proc[i].opt, option_proc[i].desc);
503                 if (option_proc[i].arg)
504                         _wayland_tbm_monitor_request_printf(r, "\t\t  %s\n", option_proc[i].arg);
505                 if (option_proc[i].ex)
506                         _wayland_tbm_monitor_request_printf(r, "\t\t  ex) %s\n", option_proc[i].ex);
507                 _wayland_tbm_monitor_request_printf(r, "\n");
508         }
509 }
510
511 static struct wayland_tbm_monitore_request *
512 _wayland_tbm_monitor_request_create(struct wl_client *client,
513                                             struct wl_resource *resource, const char *options)
514 {
515         char *end = NULL;
516         char path[256];
517         int i;
518         int pid;
519         static int id_count = 1;
520
521         struct wayland_tbm_monitore_request *r = calloc(1, sizeof(struct wayland_tbm_monitore_request));
522         memset(r, 0 , sizeof(struct wayland_tbm_monitore_request));
523
524         struct wayland_tbm_server *tbm_srv =
525                         (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
526
527         /* copy options to a local memory */
528         snprintf(r->options, sizeof(r->options), "%s", options);
529         snprintf(r->arg_mem, sizeof(r->arg_mem), "%s", options);
530
531         r->wl_client = client;
532         r->wl_resource = resource;
533         r->reply = r->msg;
534         r->len = WL_TBM_MONITOR_REPLY_MSG_LEN;
535         r->tbm_srv = tbm_srv;
536         r->id = id_count++;
537         r->path.console = 1;
538         wl_list_init(&r->link);
539
540         /* get pid */
541         wl_client_get_credentials(r->wl_client, &pid, NULL, NULL);
542         _wayland_tbm_util_get_appname_from_pid(pid, r->app_name);
543         _wayland_tbm_util_get_appname_brief(r->app_name);
544
545         /* get access to the console of a wayland-tbm-monitor application */
546         snprintf(path, sizeof(path), "/proc/%d/fd/1", pid);
547         r->console = fopen(path, "a");
548         if (!r->console) {
549                 _wayland_tbm_monitor_request_printf(r, "Can't get access to the console\n");
550                 return r;
551         }
552
553         /* get cwd of the client */
554         snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
555         if (readlink(path, r->cwd, sizeof(r->cwd)) < 0) {
556                 _wayland_tbm_monitor_request_printf(r, "Can't get cwd\n");
557                 return r;
558         }
559
560         /* parse options */
561         r->argv[r->argc] = strtok_r(r->arg_mem, " ", &end);
562         while (r->argv[r->argc]) {
563                 r->argc++;
564                 if (r->argc == WL_TBM_MONITOR_ARGS_MAX) {
565                         _wayland_tbm_monitor_request_printf(r, "Too many arguments\n");
566                         r->argc = 0;
567                         break;
568                 }
569                 r->argv[r->argc] = strtok_r(NULL, " ", &end);
570         }
571
572         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]);
573
574         /* execute */
575         if (r->argc > 0) {
576                 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
577                         if (r->argv[0][0] == '-' && !strncmp(r->argv[0] + 1, option_proc[i].opt, 32)) {
578                                 if (option_proc[i].func) {
579                                         wl_list_insert(&tbm_srv->tbm_monitor_request_list, &r->link);
580                                         option_proc[i].func(r);
581                                 } else {
582                                         _wayland_tbm_monitor_request_printf(r, "'%s' not implemented\n", r->argv[0]);
583                                 }
584                                 return r;
585                         }
586                 }
587         }
588
589
590         _wayland_tbm_monitor_request_printf(r, "'%s' is unknown options\n", r->argv[0]);
591         _wayland_tbm_monitor_server_usage(r);
592         return r;
593
594 }
595
596 struct wayland_tbm_monitore_request *
597 _wayland_tbm_monitor_get_request_by_id(struct wayland_tbm_server *tbm_srv, const char *id_str)
598 {
599         struct wayland_tbm_monitore_request *r = NULL;
600         unsigned int id = 0;
601
602         if (sscanf(id_str, "%d", &id) != 1)
603                 return NULL;
604
605         wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
606                 if (r->id == id)
607                         return r;
608
609         return NULL;
610 }
611
612 struct wayland_tbm_monitore_request *
613 _wayland_tbm_monitor_get_request_by_resource(struct wayland_tbm_server *tbm_srv,
614                                                                                          struct wl_resource *resource)
615 {
616         struct wayland_tbm_monitore_request *r = NULL;
617         wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
618                 if (r->wl_resource == resource)
619                         return r;
620
621         return NULL;
622 }
623
624 static void
625 _wayland_tbm_monitor_impl_responce_to_server(struct wl_client *client,
626                                                                                          struct wl_resource *resource,
627                                                                                          const char *message, const char *request_id)
628 {
629         struct wayland_tbm_monitore_request *r = NULL;
630         struct wayland_tbm_server *tbm_srv = NULL;
631
632         tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
633         r = _wayland_tbm_monitor_get_request_by_id(tbm_srv, request_id);
634         if (r == NULL)
635                 return;
636
637         _wayland_tbm_monitor_request_printf(r, "%s", message);
638         _wayland_tbm_monitor_request_unref(r);
639 }
640
641 static void
642 _wayland_tbm_monitor_impl_request_to_sever(struct wl_client *client,
643                                                                                    struct wl_resource *resource,
644                                                                                    const char *options)
645 {
646         struct wayland_tbm_monitore_request *r  = NULL;
647         uid_t uid = 0;
648
649         wl_client_get_credentials(client, NULL, &uid, NULL);
650         if (uid != 0) {
651                 wl_tbm_monitor_send_done(resource, "wayland-tbm-monitor: SHOULD be a superuser.\n");
652                 return;
653         }
654
655         r = _wayland_tbm_monitor_request_create(client, resource, options);
656         if (r->wait_count == 0) {
657                 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
658                 _wayland_tbm_monitor_request_delete(r);
659         }
660 }
661
662 static void
663 _wayland_tbm_monitor_impl_destroy(struct wl_client *client,
664                                         struct wl_resource *wl_tbm_monitor)
665 {
666 #ifdef DEBUG_TRACE
667         pid_t pid;
668
669         wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
670         WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
671 #endif
672
673         wl_resource_destroy(wl_tbm_monitor);
674 }
675
676 static void
677 _wayland_tbm_monitor_destroy_resource(struct wl_resource *wl_tbm_monitor)
678 {
679         struct wayland_tbm_monitore_request *r = NULL;
680         struct wayland_tbm_server *tbm_srv = NULL;
681
682 #ifdef DEBUG_TRACE
683         pid_t pid;
684
685         wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
686         WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
687 #endif
688
689         /* delete all requests from this client */
690         tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(wl_tbm_monitor);
691         while ((r = _wayland_tbm_monitor_get_request_by_resource(tbm_srv, wl_tbm_monitor)) != NULL)
692                 _wayland_tbm_monitor_request_delete(r);
693
694         wl_list_remove(wl_resource_get_link(wl_tbm_monitor));
695 }
696
697 static const struct wl_tbm_monitor_interface _wayland_tbm_monitor_implementation = {
698         _wayland_tbm_monitor_impl_destroy,
699         _wayland_tbm_monitor_impl_request_to_sever,
700         _wayland_tbm_monitor_impl_responce_to_server,
701 };
702
703 static void
704 _wayland_tbm_monitor_bind_cb(struct wl_client *client, void *data,
705                             uint32_t version, uint32_t id)
706 {
707         struct wayland_tbm_server *tbm_srv = (struct wayland_tbm_server*)data;
708         struct wl_resource *wl_tbm_monitor;
709
710         wl_tbm_monitor = wl_resource_create(client, &wl_tbm_monitor_interface, 2, id);
711         if (!wl_tbm_monitor) {
712                 wl_client_post_no_memory(client);
713                 return;
714         }
715
716         wl_resource_set_implementation(wl_tbm_monitor,
717                                                                    &_wayland_tbm_monitor_implementation,
718                                                                    tbm_srv,
719                                                                    _wayland_tbm_monitor_destroy_resource);
720         wl_list_insert(&tbm_srv->tbm_monitor_list, wl_resource_get_link(wl_tbm_monitor));
721
722 #ifdef DEBUG_TRACE
723         pid_t pid;
724
725         wl_client_get_credentials(client, &pid, NULL, NULL);
726         WL_TBM_TRACE("wl_tbm_monitor bind. client=%d\n", pid);
727 #endif
728 }
729
730 int wayland_tbm_monitor_server_init(struct wayland_tbm_server *tbm_srv)
731 {
732         tbm_srv->wl_tbm_monitor_global = wl_global_create(tbm_srv->display,
733                                         &wl_tbm_monitor_interface, 1, tbm_srv,
734                                         _wayland_tbm_monitor_bind_cb);
735         WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv->wl_tbm_monitor_global, 0);
736         wl_list_init(&tbm_srv->tbm_monitor_list);
737         wl_list_init(&tbm_srv->tbm_monitor_request_list);
738         return 1;
739 }