Create socket in /var/run/user/${HOME}
[profile/ivi/weston.git] / wayland / wayland-server.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <dlfcn.h>
34 #include <assert.h>
35 #include <ffi.h>
36
37 #include "wayland-server.h"
38 #include "wayland-server-protocol.h"
39 #include "connection.h"
40
41 struct wl_socket {
42         int fd;
43         struct sockaddr_un addr;
44         struct wl_list link;
45 };
46
47 struct wl_client {
48         struct wl_connection *connection;
49         struct wl_event_source *source;
50         struct wl_display *display;
51         struct wl_list resource_list;
52         uint32_t id_count;
53 };
54
55 struct wl_display {
56         struct wl_object base;
57         struct wl_event_loop *loop;
58         struct wl_hash_table *objects;
59         int run;
60
61         struct wl_list frame_list;
62         uint32_t client_id_range;
63         uint32_t id;
64
65         struct wl_list global_list;
66         struct wl_list socket_list;
67 };
68
69 struct wl_frame_listener {
70         struct wl_resource resource;
71         struct wl_client *client;
72         uint32_t key;
73         struct wl_list link;
74 };
75
76 struct wl_global {
77         struct wl_object *object;
78         wl_client_connect_func_t func;
79         struct wl_list link;
80 };
81
82 WL_EXPORT struct wl_surface wl_grab_surface;
83
84 static int wl_debug = 0;
85
86 WL_EXPORT void
87 wl_client_post_event(struct wl_client *client, struct wl_object *sender,
88                      uint32_t opcode, ...)
89 {
90         struct wl_closure *closure;
91         va_list ap;
92
93         if (client == NULL)
94                 /* wl_grab_surface case */
95                 return;
96
97         va_start(ap, opcode);
98         closure = wl_connection_vmarshal(client->connection,
99                                          sender, opcode, ap,
100                                          &sender->interface->events[opcode]);
101         va_end(ap);
102
103         wl_closure_send(closure, client->connection);
104
105         if (wl_debug) {
106                 fprintf(stderr, " -> ");
107                 wl_closure_print(closure, sender);
108         }
109
110         wl_closure_destroy(closure);
111 }
112
113 static void
114 wl_client_connection_data(int fd, uint32_t mask, void *data)
115 {
116         struct wl_client *client = data;
117         struct wl_connection *connection = client->connection;
118         struct wl_object *object;
119         struct wl_closure *closure;
120         const struct wl_message *message;
121         uint32_t p[2], opcode, size;
122         uint32_t cmask = 0;
123         int len;
124
125         if (mask & WL_EVENT_READABLE)
126                 cmask |= WL_CONNECTION_READABLE;
127         if (mask & WL_EVENT_WRITEABLE)
128                 cmask |= WL_CONNECTION_WRITABLE;
129
130         len = wl_connection_data(connection, cmask);
131         if (len < 0) {
132                 wl_client_destroy(client);
133                 return;
134         }
135
136         while (len >= sizeof p) {
137                 wl_connection_copy(connection, p, sizeof p);
138                 opcode = p[1] & 0xffff;
139                 size = p[1] >> 16;
140                 if (len < size)
141                         break;
142
143                 object = wl_hash_table_lookup(client->display->objects, p[0]);
144                 if (object == NULL) {
145                         wl_client_post_event(client, &client->display->base,
146                                              WL_DISPLAY_INVALID_OBJECT, p[0]);
147                         wl_connection_consume(connection, size);
148                         len -= size;
149                         continue;
150                 }
151
152                 if (opcode >= object->interface->method_count) {
153                         wl_client_post_event(client, &client->display->base,
154                                              WL_DISPLAY_INVALID_METHOD, p[0], opcode);
155                         wl_connection_consume(connection, size);
156                         len -= size;
157                         continue;
158                 }
159
160                 message = &object->interface->methods[opcode];
161                 closure = wl_connection_demarshal(client->connection, size,
162                                                   client->display->objects,
163                                                   message);
164                 len -= size;
165
166                 if (closure == NULL && errno == EINVAL) {
167                         wl_client_post_event(client, &client->display->base,
168                                              WL_DISPLAY_INVALID_METHOD,
169                                              p[0], opcode);
170                         continue;
171                 } else if (closure == NULL && errno == ENOMEM) {
172                         wl_client_post_no_memory(client);
173                         continue;
174                 }
175
176
177                 if (wl_debug)
178                         wl_closure_print(closure, object);
179
180                 wl_closure_invoke(closure, object,
181                                   object->implementation[opcode], client);
182
183                 wl_closure_destroy(closure);
184         }
185 }
186
187 static int
188 wl_client_connection_update(struct wl_connection *connection,
189                             uint32_t mask, void *data)
190 {
191         struct wl_client *client = data;
192         uint32_t emask = 0;
193
194         if (mask & WL_CONNECTION_READABLE)
195                 emask |= WL_EVENT_READABLE;
196         if (mask & WL_CONNECTION_WRITABLE)
197                 emask |= WL_EVENT_WRITEABLE;
198
199         return wl_event_source_fd_update(client->source, mask);
200 }
201
202 WL_EXPORT struct wl_display *
203 wl_client_get_display(struct wl_client *client)
204 {
205         return client->display;
206 }
207
208 static void
209 wl_display_post_range(struct wl_display *display, struct wl_client *client)
210 {
211         wl_client_post_event(client, &client->display->base,
212                              WL_DISPLAY_RANGE, display->client_id_range);
213         display->client_id_range += 256;
214         client->id_count += 256;
215 }
216
217 static struct wl_client *
218 wl_client_create(struct wl_display *display, int fd)
219 {
220         struct wl_client *client;
221         struct wl_global *global;
222
223         client = malloc(sizeof *client);
224         if (client == NULL)
225                 return NULL;
226
227         memset(client, 0, sizeof *client);
228         client->display = display;
229         client->source = wl_event_loop_add_fd(display->loop, fd,
230                                               WL_EVENT_READABLE,
231                                               wl_client_connection_data, client);
232         client->connection =
233                 wl_connection_create(fd, wl_client_connection_update, client);
234
235         wl_list_init(&client->resource_list);
236
237         wl_display_post_range(display, client);
238
239         wl_list_for_each(global, &display->global_list, link)
240                 wl_client_post_event(client, &client->display->base,
241                                      WL_DISPLAY_GLOBAL,
242                                      global->object,
243                                      global->object->interface->name,
244                                      global->object->interface->version);
245
246         wl_list_for_each(global, &display->global_list, link)
247                 if (global->func)
248                         global->func(client, global->object);
249
250         return client;
251 }
252
253 WL_EXPORT void
254 wl_client_add_resource(struct wl_client *client,
255                        struct wl_resource *resource)
256 {
257         struct wl_display *display = client->display;
258
259         if (client->id_count-- < 64)
260                 wl_display_post_range(display, client);
261
262         wl_hash_table_insert(client->display->objects,
263                              resource->base.id, resource);
264         wl_list_insert(client->resource_list.prev, &resource->link);
265 }
266
267 WL_EXPORT void
268 wl_client_post_no_memory(struct wl_client *client)
269 {
270         wl_client_post_event(client,
271                              &client->display->base,
272                              WL_DISPLAY_NO_MEMORY);
273 }
274
275 WL_EXPORT void
276 wl_client_post_global(struct wl_client *client, struct wl_object *object)
277 {
278         wl_client_post_event(client,
279                              &client->display->base,
280                              WL_DISPLAY_GLOBAL,
281                              object,
282                              object->interface->name,
283                              object->interface->version);
284 }
285
286 WL_EXPORT void
287 wl_resource_destroy(struct wl_resource *resource, struct wl_client *client)
288 {
289         struct wl_display *display = client->display;
290
291         wl_list_remove(&resource->link);
292         if (resource->base.id > 0)
293                 wl_hash_table_remove(display->objects, resource->base.id);
294         resource->destroy(resource, client);
295 }
296
297 WL_EXPORT void
298 wl_client_destroy(struct wl_client *client)
299 {
300         struct wl_resource *resource, *tmp;
301
302         printf("disconnect from client %p\n", client);
303
304         wl_list_for_each_safe(resource, tmp, &client->resource_list, link)
305                 wl_resource_destroy(resource, client);
306
307         wl_event_source_remove(client->source);
308         wl_connection_destroy(client->connection);
309         free(client);
310 }
311
312 WL_EXPORT void
313 wl_input_device_set_pointer_focus(struct wl_input_device *device,
314                                   struct wl_surface *surface,
315                                   uint32_t time,
316                                   int32_t x, int32_t y,
317                                   int32_t sx, int32_t sy)
318 {
319         if (device->pointer_focus == surface)
320                 return;
321
322         if (device->pointer_focus &&
323             (!surface || device->pointer_focus->client != surface->client))
324                 wl_client_post_event(device->pointer_focus->client,
325                                      &device->base,
326                                      WL_INPUT_DEVICE_POINTER_FOCUS,
327                                      time, NULL, 0, 0, 0, 0);
328         if (surface)
329                 wl_client_post_event(surface->client,
330                                      &device->base,
331                                      WL_INPUT_DEVICE_POINTER_FOCUS,
332                                      time, surface, x, y, sx, sy);
333
334         device->pointer_focus = surface;
335         device->pointer_focus_time = time;
336 }
337
338 WL_EXPORT void
339 wl_input_device_set_keyboard_focus(struct wl_input_device *device,
340                                    struct wl_surface *surface,
341                                    uint32_t time)
342 {
343         if (device->keyboard_focus == surface)
344                 return;
345
346         if (device->keyboard_focus &&
347             (!surface || device->keyboard_focus->client != surface->client))
348                 wl_client_post_event(device->keyboard_focus->client,
349                                      &device->base,
350                                      WL_INPUT_DEVICE_KEYBOARD_FOCUS,
351                                      time, NULL, &device->keys);
352
353         if (surface)
354                 wl_client_post_event(surface->client,
355                                      &device->base,
356                                      WL_INPUT_DEVICE_KEYBOARD_FOCUS,
357                                      time, surface, &device->keys);
358
359         device->keyboard_focus = surface;
360         device->keyboard_focus_time = time;
361 }
362
363 static void
364 display_sync(struct wl_client *client,
365                struct wl_display *display, uint32_t key)
366 {
367         wl_client_post_event(client, &display->base, WL_DISPLAY_KEY, key, 0);
368 }
369
370 static void
371 destroy_frame_listener(struct wl_resource *resource, struct wl_client *client)
372 {
373         struct wl_frame_listener *listener =
374                 container_of(resource, struct wl_frame_listener, resource);
375
376         wl_list_remove(&listener->link);
377         free(listener);
378 }
379
380 static void
381 display_frame(struct wl_client *client,
382               struct wl_display *display, uint32_t key)
383 {
384         struct wl_frame_listener *listener;
385
386         listener = malloc(sizeof *listener);
387         if (listener == NULL) {
388                 wl_client_post_no_memory(client);
389                 return;
390         }
391
392         /* The listener is a resource so we destroy it when the client
393          * goes away. */
394         listener->resource.destroy = destroy_frame_listener;
395         listener->resource.base.id = 0;
396         listener->client = client;
397         listener->key = key;
398         wl_list_insert(client->resource_list.prev, &listener->resource.link);
399         wl_list_insert(display->frame_list.prev, &listener->link);
400 }
401
402 struct wl_display_interface display_interface = {
403         display_sync,
404         display_frame
405 };
406
407
408 WL_EXPORT struct wl_display *
409 wl_display_create(void)
410 {
411         struct wl_display *display;
412         const char *debug;
413
414         debug = getenv("WAYLAND_DEBUG");
415         if (debug)
416                 wl_debug = 1;
417
418         display = malloc(sizeof *display);
419         if (display == NULL)
420                 return NULL;
421
422         display->loop = wl_event_loop_create();
423         if (display->loop == NULL) {
424                 free(display);
425                 return NULL;
426         }
427
428         display->objects = wl_hash_table_create();
429         if (display->objects == NULL) {
430                 free(display);
431                 return NULL;
432         }
433
434         wl_list_init(&display->frame_list);
435         wl_list_init(&display->global_list);
436         wl_list_init(&display->socket_list);
437
438         display->client_id_range = 256; /* Gah, arbitrary... */
439
440         display->id = 1;
441         display->base.interface = &wl_display_interface;
442         display->base.implementation = (void (**)(void)) &display_interface;
443         wl_display_add_object(display, &display->base);
444         if (wl_display_add_global(display, &display->base, NULL)) {
445                 wl_event_loop_destroy(display->loop);
446                 free(display);
447                 return NULL;
448         }
449
450         return display;
451 }
452
453 WL_EXPORT void
454 wl_display_destroy(struct wl_display *display)
455 {
456         struct wl_socket *s, *next;
457
458         wl_event_loop_destroy(display->loop);
459         wl_hash_table_destroy(display->objects);
460         
461         wl_list_for_each_safe(s, next, &display->socket_list, link) {
462                 close(s->fd);
463                 unlink(s->addr.sun_path);
464                 free(s);
465         }
466
467         free(display);
468 }
469
470 WL_EXPORT void
471 wl_display_add_object(struct wl_display *display, struct wl_object *object)
472 {
473         object->id = display->id++;
474         wl_hash_table_insert(display->objects, object->id, object);
475 }
476
477 WL_EXPORT int
478 wl_display_add_global(struct wl_display *display,
479                       struct wl_object *object, wl_client_connect_func_t func)
480 {
481         struct wl_global *global;
482
483         global = malloc(sizeof *global);
484         if (global == NULL)
485                 return -1;
486
487         global->object = object;
488         global->func = func;
489         wl_list_insert(display->global_list.prev, &global->link);
490
491         return 0;       
492 }
493
494 WL_EXPORT void
495 wl_display_post_frame(struct wl_display *display, uint32_t time)
496 {
497         struct wl_frame_listener *listener, *next;
498
499         wl_list_for_each_safe(listener, next, &display->frame_list, link) {
500                 wl_client_post_event(listener->client, &display->base,
501                                      WL_DISPLAY_KEY, listener->key, time);
502                 wl_resource_destroy(&listener->resource, listener->client);
503         }
504 }
505
506 WL_EXPORT struct wl_event_loop *
507 wl_display_get_event_loop(struct wl_display *display)
508 {
509         return display->loop;
510 }
511
512 WL_EXPORT void
513 wl_display_terminate(struct wl_display *display)
514 {
515         display->run = 0;
516 }
517
518 WL_EXPORT void
519 wl_display_run(struct wl_display *display)
520 {
521         display->run = 1;
522
523         while (display->run)
524                 wl_event_loop_dispatch(display->loop, -1);
525 }
526
527 static void
528 socket_data(int fd, uint32_t mask, void *data)
529 {
530         struct wl_display *display = data;
531         struct sockaddr_un name;
532         socklen_t length;
533         int client_fd;
534
535         length = sizeof name;
536         client_fd = accept (fd, (struct sockaddr *) &name, &length);
537         if (client_fd < 0)
538                 fprintf(stderr, "failed to accept\n");
539
540         wl_client_create(display, client_fd);
541 }
542
543 WL_EXPORT int
544 wl_display_add_socket(struct wl_display *display, const char *name)
545 {
546         struct wl_socket *s;
547         socklen_t size, name_size;
548         const char *runtime_dir;
549
550         s = malloc(sizeof *s);
551         if (socket == NULL)
552                 return -1;
553
554         s->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
555         if (s->fd < 0)
556                 return -1;
557
558         runtime_dir = getenv("XDG_RUNTIME_DIR");
559         if (runtime_dir == NULL) {
560                 runtime_dir = ".";
561                 fprintf(stderr,
562                         "XDG_RUNTIME_DIR not set, falling back to %s\n",
563                         runtime_dir);
564         }
565
566         if (name == NULL)
567                 name = getenv("WAYLAND_DISPLAY");
568         if (name == NULL)
569                 name = "wayland-0";
570
571         memset(&s->addr, 0, sizeof s->addr);
572         s->addr.sun_family = AF_LOCAL;
573         name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
574                              "%s/%s", runtime_dir, name) + 1;
575         fprintf(stderr, "using socket %s\n", s->addr.sun_path);
576
577         size = offsetof (struct sockaddr_un, sun_path) + name_size;
578         if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0)
579                 return -1;
580
581         if (listen(s->fd, 1) < 0)
582                 return -1;
583
584         wl_event_loop_add_fd(display->loop, s->fd,
585                              WL_EVENT_READABLE,
586                              socket_data, display);
587         wl_list_insert(display->socket_list.prev, &s->link);
588
589         return 0;
590 }