server: use the event sending wrappers
[profile/ivi/wayland.git] / src / 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 #define _GNU_SOURCE
24
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <stdbool.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/socket.h>
35 #include <sys/un.h>
36 #include <dlfcn.h>
37 #include <assert.h>
38 #include <sys/time.h>
39 #include <fcntl.h>
40 #include <sys/file.h>
41 #include <sys/stat.h>
42 #include <ffi.h>
43
44 #include "wayland-private.h"
45 #include "wayland-server.h"
46 #include "wayland-server-protocol.h"
47
48 struct wl_socket {
49         int fd;
50         int fd_lock;
51         struct sockaddr_un addr;
52         char lock_addr[113];
53         struct wl_list link;
54         struct wl_event_source *source;
55 };
56
57 struct wl_client {
58         struct wl_connection *connection;
59         struct wl_event_source *source;
60         struct wl_display *display;
61         struct wl_resource *display_resource;
62         uint32_t id_count;
63         uint32_t mask;
64         struct wl_list link;
65         struct wl_map objects;
66         struct ucred ucred;
67         int error;
68 };
69
70 struct wl_display {
71         struct wl_event_loop *loop;
72         int run;
73
74         uint32_t id;
75
76         struct wl_list global_list;
77         struct wl_list socket_list;
78         struct wl_list client_list;
79 };
80
81 struct wl_global {
82         const struct wl_interface *interface;
83         uint32_t name;
84         void *data;
85         wl_global_bind_func_t bind;
86         struct wl_list link;
87 };
88
89 static int wl_debug = 0;
90
91 static void
92 destroy_client(void *data)
93 {
94         struct wl_client *client = data;
95
96         wl_client_destroy(client);
97 }
98
99 WL_EXPORT void
100 wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
101 {
102         struct wl_closure *closure;
103         struct wl_object *object = &resource->object;
104         va_list ap;
105
106         va_start(ap, opcode);
107         closure = wl_connection_vmarshal(resource->client->connection,
108                                          object, opcode, ap,
109                                          &object->interface->events[opcode]);
110         va_end(ap);
111
112         if (closure == NULL)
113                 return;
114
115         if (wl_closure_send(closure, resource->client->connection))
116                 wl_event_loop_add_idle(resource->client->display->loop,
117                                        destroy_client, resource->client);
118
119         if (wl_debug)
120                 wl_closure_print(closure, object, true);
121
122         wl_closure_destroy(closure);
123 }
124
125
126 WL_EXPORT void
127 wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
128 {
129         struct wl_closure *closure;
130         struct wl_object *object = &resource->object;
131         va_list ap;
132
133         va_start(ap, opcode);
134         closure = wl_connection_vmarshal(resource->client->connection,
135                                          object, opcode, ap,
136                                          &object->interface->events[opcode]);
137         va_end(ap);
138
139         if (closure == NULL)
140                 return;
141
142         if (wl_closure_queue(closure, resource->client->connection))
143                 wl_event_loop_add_idle(resource->client->display->loop,
144                                        destroy_client, resource->client);
145
146         if (wl_debug)
147                 wl_closure_print(closure, object, true);
148
149         wl_closure_destroy(closure);
150 }
151
152 WL_EXPORT void
153 wl_resource_post_error(struct wl_resource *resource,
154                        uint32_t code, const char *msg, ...)
155 {
156         struct wl_client *client = resource->client;
157         char buffer[128];
158         va_list ap;
159
160         va_start(ap, msg);
161         vsnprintf(buffer, sizeof buffer, msg, ap);
162         va_end(ap);
163
164         client->error = 1;
165
166         /*
167          * When a client aborts, its resources are destroyed in id order,
168          * which means the display resource is destroyed first. If destruction
169          * of any later resources results in a protocol error, we end up here
170          * with a NULL display_resource. Do not try to send errors to an
171          * already dead client.
172          */
173         if (!client->display_resource)
174                 return;
175
176         wl_resource_post_event(client->display_resource,
177                                WL_DISPLAY_ERROR, resource, code, buffer);
178 }
179
180 static int
181 wl_client_connection_data(int fd, uint32_t mask, void *data)
182 {
183         struct wl_client *client = data;
184         struct wl_connection *connection = client->connection;
185         struct wl_resource *resource;
186         struct wl_object *object;
187         struct wl_closure *closure;
188         const struct wl_message *message;
189         uint32_t p[2], opcode, size;
190         uint32_t cmask = 0;
191         int len;
192
193         if (mask & WL_EVENT_READABLE)
194                 cmask |= WL_CONNECTION_READABLE;
195         if (mask & WL_EVENT_WRITABLE)
196                 cmask |= WL_CONNECTION_WRITABLE;
197
198         len = wl_connection_data(connection, cmask);
199         if (len < 0) {
200                 wl_client_destroy(client);
201                 return 1;
202         }
203
204         while (len >= sizeof p) {
205                 wl_connection_copy(connection, p, sizeof p);
206                 opcode = p[1] & 0xffff;
207                 size = p[1] >> 16;
208                 if (len < size)
209                         break;
210
211                 resource = wl_map_lookup(&client->objects, p[0]);
212                 if (resource == NULL) {
213                         wl_resource_post_error(client->display_resource,
214                                                WL_DISPLAY_ERROR_INVALID_OBJECT,
215                                                "invalid object %d", p[0]);
216                         break;
217                 }
218
219                 object = &resource->object;
220                 if (opcode >= object->interface->method_count) {
221                         wl_resource_post_error(client->display_resource,
222                                                WL_DISPLAY_ERROR_INVALID_METHOD,
223                                                "invalid method %d, object %s@%d",
224                                                object->interface->name,
225                                                object->id, opcode);
226                         break;
227                 }
228
229                 message = &object->interface->methods[opcode];
230                 closure = wl_connection_demarshal(client->connection, size,
231                                                   &client->objects, message);
232                 len -= size;
233
234                 if (closure == NULL && errno == EINVAL) {
235                         wl_resource_post_error(client->display_resource,
236                                                WL_DISPLAY_ERROR_INVALID_METHOD,
237                                                "invalid arguments for %s@%d.%s",
238                                                object->interface->name,
239                                                object->id,
240                                                message->name);
241                         break;
242                 } else if (closure == NULL && errno == ENOMEM) {
243                         wl_resource_post_no_memory(resource);
244                         break;
245                 }
246
247                 if (wl_debug)
248                         wl_closure_print(closure, object, false); 
249
250                 wl_closure_invoke(closure, object,
251                                   object->implementation[opcode], client);
252
253                 wl_closure_destroy(closure);
254
255                 if (client->error)
256                         break;
257         }
258
259         if (client->error)
260                 wl_client_destroy(client);
261
262         return 1;
263 }
264
265 static int
266 wl_client_connection_update(struct wl_connection *connection,
267                             uint32_t mask, void *data)
268 {
269         struct wl_client *client = data;
270         uint32_t emask = 0;
271
272         client->mask = mask;
273         if (mask & WL_CONNECTION_READABLE)
274                 emask |= WL_EVENT_READABLE;
275         if (mask & WL_CONNECTION_WRITABLE)
276                 emask |= WL_EVENT_WRITABLE;
277
278         return wl_event_source_fd_update(client->source, emask);
279 }
280
281 WL_EXPORT void
282 wl_client_flush(struct wl_client *client)
283 {
284         if (client->mask & WL_CONNECTION_WRITABLE)
285                 wl_connection_data(client->connection, WL_CONNECTION_WRITABLE);
286 }
287
288 WL_EXPORT struct wl_display *
289 wl_client_get_display(struct wl_client *client)
290 {
291         return client->display;
292 }
293
294 static void
295 bind_display(struct wl_client *client,
296              void *data, uint32_t version, uint32_t id);
297
298 WL_EXPORT struct wl_client *
299 wl_client_create(struct wl_display *display, int fd)
300 {
301         struct wl_client *client;
302         socklen_t len;
303
304         client = malloc(sizeof *client);
305         if (client == NULL)
306                 return NULL;
307
308         memset(client, 0, sizeof *client);
309         client->display = display;
310         client->source = wl_event_loop_add_fd(display->loop, fd,
311                                               WL_EVENT_READABLE,
312                                               wl_client_connection_data, client);
313
314         len = sizeof client->ucred;
315         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
316                        &client->ucred, &len) < 0) {
317                 free(client);
318                 return NULL;
319         }
320
321         client->connection =
322                 wl_connection_create(fd, wl_client_connection_update, client);
323         if (client->connection == NULL) {
324                 free(client);
325                 return NULL;
326         }
327
328         wl_map_init(&client->objects);
329
330         if (wl_map_insert_at(&client->objects, 0, NULL) < 0) {
331                 wl_map_release(&client->objects);
332                 free(client);
333                 return NULL;
334         }
335
336         bind_display(client, display, 1, 1);
337
338         wl_list_insert(display->client_list.prev, &client->link);
339
340         return client;
341 }
342
343 WL_EXPORT void
344 wl_client_get_credentials(struct wl_client *client,
345                           pid_t *pid, uid_t *uid, gid_t *gid)
346 {
347         if (pid)
348                 *pid = client->ucred.pid;
349         if (uid)
350                 *uid = client->ucred.uid;
351         if (gid)
352                 *gid = client->ucred.gid;
353 }
354
355 WL_EXPORT void
356 wl_client_add_resource(struct wl_client *client,
357                        struct wl_resource *resource)
358 {
359         if (resource->object.id == 0)
360                 resource->object.id =
361                         wl_map_insert_new(&client->objects,
362                                           WL_MAP_SERVER_SIDE, resource);
363         else
364                 wl_map_insert_at(&client->objects,
365                                  resource->object.id, resource);
366
367         resource->client = client;
368         wl_list_init(&resource->destroy_listener_list);
369 }
370
371 WL_EXPORT void
372 wl_resource_post_no_memory(struct wl_resource *resource)
373 {
374         wl_resource_post_error(resource->client->display_resource,
375                                WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
376 }
377
378 static void
379 destroy_resource(void *element, void *data)
380 {
381         struct wl_resource *resource = element;
382         struct wl_listener *l, *next;
383         uint32_t *time = data;
384
385         wl_list_for_each_safe(l, next, &resource->destroy_listener_list, link)
386                 l->func(l, resource, *time);
387
388         if (resource->destroy)
389                 resource->destroy(resource);
390 }
391
392 WL_EXPORT void
393 wl_resource_destroy(struct wl_resource *resource, uint32_t time)
394 {
395         struct wl_client *client = resource->client;
396         uint32_t id;
397
398         id = resource->object.id;
399         destroy_resource(resource, &time);
400
401         if (id < WL_SERVER_ID_START) {
402                 if (client->display_resource) {
403                         wl_resource_queue_event(client->display_resource,
404                                                 WL_DISPLAY_DELETE_ID, id);
405                 }
406                 wl_map_insert_at(&client->objects, id, NULL);
407         } else {
408                 wl_map_remove(&client->objects, id);
409         }
410 }
411
412 WL_EXPORT void
413 wl_client_destroy(struct wl_client *client)
414 {
415         uint32_t time = 0;
416         
417         printf("disconnect from client %p\n", client);
418
419         wl_client_flush(client);
420         wl_map_for_each(&client->objects, destroy_resource, &time);
421         wl_map_release(&client->objects);
422         wl_event_source_remove(client->source);
423         wl_connection_destroy(client->connection);
424         wl_list_remove(&client->link);
425         free(client);
426 }
427
428 static void
429 lose_pointer_focus(struct wl_listener *listener,
430                    struct wl_resource *resource, uint32_t time)
431 {
432         struct wl_input_device *device =
433                 container_of(listener, struct wl_input_device,
434                              pointer_focus_listener);
435
436         device->pointer_focus_resource = NULL;
437 }
438
439 static void
440 lose_keyboard_focus(struct wl_listener *listener,
441                     struct wl_resource *resource, uint32_t time)
442 {
443         struct wl_input_device *device =
444                 container_of(listener, struct wl_input_device,
445                              keyboard_focus_listener);
446
447         device->keyboard_focus_resource = NULL;
448 }
449
450 static void
451 default_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
452                    struct wl_surface *surface, int32_t x, int32_t y)
453 {
454         struct wl_input_device *device = grab->input_device;
455
456         if (device->button_count > 0)
457                 return;
458
459         wl_input_device_set_pointer_focus(device, surface, time, x, y);
460 }
461
462 static void
463 default_grab_motion(struct wl_pointer_grab *grab,
464                     uint32_t time, int32_t x, int32_t y)
465 {
466         struct wl_resource *resource;
467
468         resource = grab->input_device->pointer_focus_resource;
469         if (resource)
470                 wl_input_device_send_motion(resource, time, x, y);
471 }
472
473 static void
474 default_grab_button(struct wl_pointer_grab *grab,
475                     uint32_t time, int32_t button, int32_t state)
476 {
477         struct wl_input_device *device = grab->input_device;
478         struct wl_resource *resource;
479
480         resource = device->pointer_focus_resource;
481         if (resource)
482                 wl_input_device_send_button(resource, time, button, state);
483
484         if (device->button_count == 0 && state == 0)
485                 wl_input_device_set_pointer_focus(device,
486                                                   device->current, time,
487                                                   device->current_x,
488                                                   device->current_y);
489 }
490
491 static const struct wl_pointer_grab_interface
492                                 default_pointer_grab_interface = {
493         default_grab_focus,
494         default_grab_motion,
495         default_grab_button
496 };
497
498 static void
499 default_grab_key(struct wl_keyboard_grab *grab,
500                     uint32_t time, uint32_t key, int32_t state)
501 {
502         struct wl_input_device *device = grab->input_device;
503         struct wl_resource *resource;
504
505         resource = device->keyboard_focus_resource;
506         if (resource)
507                 wl_input_device_send_key(resource, time, key, state);
508 }
509
510 static const struct wl_keyboard_grab_interface
511                                 default_keyboard_grab_interface = {
512         default_grab_key
513 };
514
515 WL_EXPORT void
516 wl_input_device_init(struct wl_input_device *device)
517 {
518         memset(device, 0, sizeof *device);
519         wl_list_init(&device->resource_list);
520         wl_array_init(&device->keys);
521         device->pointer_focus_listener.func = lose_pointer_focus;
522         device->keyboard_focus_listener.func = lose_keyboard_focus;
523
524         device->default_pointer_grab.interface = &default_pointer_grab_interface;
525         device->default_pointer_grab.input_device = device;
526         device->pointer_grab = &device->default_pointer_grab;
527
528         device->default_keyboard_grab.interface = &default_keyboard_grab_interface;
529         device->default_keyboard_grab.input_device = device;
530         device->keyboard_grab = &device->default_keyboard_grab;
531
532         wl_list_init(&device->drag_resource_list);
533         device->selection_data_source = NULL;
534         wl_list_init(&device->selection_listener_list);
535
536         device->x = 100;
537         device->y = 100;
538 }
539
540 WL_EXPORT void
541 wl_input_device_release(struct wl_input_device *device)
542 {
543         if (device->keyboard_focus_resource)
544                 wl_list_remove(&device->keyboard_focus_listener.link);
545
546         if (device->pointer_focus_resource)
547                 wl_list_remove(&device->pointer_focus_listener.link);
548
549         /* XXX: What about device->resource_list? */
550
551         wl_array_release(&device->keys);
552 }
553
554 static struct wl_resource *
555 find_resource_for_surface(struct wl_list *list, struct wl_surface *surface)
556 {
557         struct wl_resource *r;
558
559         if (!surface)
560                 return NULL;
561
562         wl_list_for_each(r, list, link) {
563                 if (r->client == surface->resource.client)
564                         return r;
565         }
566
567         return NULL;
568 }
569
570 WL_EXPORT void
571 wl_input_device_set_pointer_focus(struct wl_input_device *device,
572                                   struct wl_surface *surface,
573                                   uint32_t time,
574                                   int32_t sx, int32_t sy)
575 {
576         struct wl_resource *resource;
577
578         if (device->pointer_focus == surface)
579                 return;
580
581         if (device->pointer_focus_resource) {
582                 wl_input_device_send_pointer_leave(
583                         device->pointer_focus_resource,
584                         time, device->pointer_focus);
585                 wl_list_remove(&device->pointer_focus_listener.link);
586         }
587
588         resource = find_resource_for_surface(&device->resource_list, surface);
589         if (resource) {
590                 wl_input_device_send_pointer_enter(resource, time,
591                                                    surface, sx, sy);
592                 wl_list_insert(resource->destroy_listener_list.prev,
593                                &device->pointer_focus_listener.link);
594         }
595
596         device->pointer_focus_resource = resource;
597         device->pointer_focus = surface;
598         device->pointer_focus_time = time;
599         device->default_pointer_grab.focus = surface;
600 }
601
602 WL_EXPORT void
603 wl_input_device_set_keyboard_focus(struct wl_input_device *device,
604                                    struct wl_surface *surface,
605                                    uint32_t time)
606 {
607         struct wl_resource *resource;
608
609         if (device->keyboard_focus == surface)
610                 return;
611
612         if (device->keyboard_focus_resource) {
613                 wl_input_device_send_keyboard_leave(
614                         device->keyboard_focus_resource,
615                         time, device->keyboard_focus);
616                 wl_list_remove(&device->keyboard_focus_listener.link);
617         }
618
619         resource = find_resource_for_surface(&device->resource_list, surface);
620         if (resource) {
621                 wl_input_device_send_keyboard_enter(resource, time,
622                                                     surface, &device->keys);
623                 wl_list_insert(resource->destroy_listener_list.prev,
624                                &device->keyboard_focus_listener.link);
625         }
626
627         device->keyboard_focus_resource = resource;
628         device->keyboard_focus = surface;
629         device->keyboard_focus_time = time;
630 }
631
632 WL_EXPORT void
633 wl_input_device_start_keyboard_grab(struct wl_input_device *device,
634                            struct wl_keyboard_grab *grab, uint32_t time)
635 {
636         device->keyboard_grab = grab;
637         grab->input_device = device;
638
639 }
640
641 WL_EXPORT void
642 wl_input_device_end_keyboard_grab(struct wl_input_device *device, uint32_t time)
643 {
644         device->keyboard_grab = &device->default_keyboard_grab;
645 }
646
647 WL_EXPORT void
648 wl_input_device_start_pointer_grab(struct wl_input_device *device,
649                            struct wl_pointer_grab *grab, uint32_t time)
650 {
651         const struct wl_pointer_grab_interface *interface;
652
653         device->pointer_grab = grab;
654         interface = device->pointer_grab->interface;
655         grab->input_device = device;
656
657         if (device->current)
658                 interface->focus(device->pointer_grab, time, device->current,
659                                  device->current_x, device->current_y);
660 }
661
662 WL_EXPORT void
663 wl_input_device_end_pointer_grab(struct wl_input_device *device, uint32_t time)
664 {
665         const struct wl_pointer_grab_interface *interface;
666
667         device->pointer_grab = &device->default_pointer_grab;
668         interface = device->pointer_grab->interface;
669         interface->focus(device->pointer_grab, time, device->current,
670                          device->current_x, device->current_y);
671 }
672
673 static void
674 display_bind(struct wl_client *client,
675              struct wl_resource *resource, uint32_t name,
676              const char *interface, uint32_t version, uint32_t id)
677 {
678         struct wl_global *global;
679         struct wl_display *display = resource->data;
680
681         wl_list_for_each(global, &display->global_list, link)
682                 if (global->name == name)
683                         break;
684
685         if (&global->link == &display->global_list)
686                 wl_resource_post_error(resource,
687                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
688                                        "invalid global %d", name);
689         else
690                 global->bind(client, global->data, version, id);
691 }
692
693 static void
694 display_sync(struct wl_client *client,
695              struct wl_resource *resource, uint32_t id)
696 {
697         struct wl_resource *callback;
698
699         callback = wl_client_add_object(client,
700                                         &wl_callback_interface, NULL, id, NULL);
701         wl_callback_send_done(callback, 0);
702         wl_resource_destroy(callback, 0);
703 }
704
705 struct wl_display_interface display_interface = {
706         display_bind,
707         display_sync,
708 };
709
710 static void
711 destroy_client_display_resource(struct wl_resource *resource)
712 {
713         resource->client->display_resource = NULL;
714         free(resource);
715 }
716
717 static void
718 bind_display(struct wl_client *client,
719              void *data, uint32_t version, uint32_t id)
720 {
721         struct wl_display *display = data;
722         struct wl_global *global;
723
724         client->display_resource =
725                 wl_client_add_object(client, &wl_display_interface,
726                                      &display_interface, id, display);
727         client->display_resource->destroy = destroy_client_display_resource;
728
729         wl_list_for_each(global, &display->global_list, link)
730                 wl_resource_post_event(client->display_resource,
731                                        WL_DISPLAY_GLOBAL,
732                                        global->name,
733                                        global->interface->name,
734                                        global->interface->version);
735 }
736
737 WL_EXPORT struct wl_display *
738 wl_display_create(void)
739 {
740         struct wl_display *display;
741         const char *debug;
742
743         debug = getenv("WAYLAND_DEBUG");
744         if (debug)
745                 wl_debug = 1;
746
747         display = malloc(sizeof *display);
748         if (display == NULL)
749                 return NULL;
750
751         display->loop = wl_event_loop_create();
752         if (display->loop == NULL) {
753                 free(display);
754                 return NULL;
755         }
756
757         wl_list_init(&display->global_list);
758         wl_list_init(&display->socket_list);
759         wl_list_init(&display->client_list);
760
761         display->id = 1;
762
763         if (!wl_display_add_global(display, &wl_display_interface, 
764                                    display, bind_display)) {
765                 wl_event_loop_destroy(display->loop);
766                 free(display);
767                 return NULL;
768         }
769
770         return display;
771 }
772
773 WL_EXPORT void
774 wl_display_destroy(struct wl_display *display)
775 {
776         struct wl_socket *s, *next;
777         struct wl_global *global, *gnext;
778
779         wl_list_for_each_safe(s, next, &display->socket_list, link) {
780                 wl_event_source_remove(s->source);
781                 close(s->fd);
782                 unlink(s->addr.sun_path);
783                 close(s->fd_lock);
784                 unlink(s->lock_addr);
785                 free(s);
786         }
787         wl_event_loop_destroy(display->loop);
788
789         wl_list_for_each_safe(global, gnext, &display->global_list, link)
790                 free(global);
791
792         free(display);
793 }
794
795 WL_EXPORT struct wl_global *
796 wl_display_add_global(struct wl_display *display,
797                       const struct wl_interface *interface,
798                       void *data, wl_global_bind_func_t bind)
799 {
800         struct wl_global *global;
801
802         global = malloc(sizeof *global);
803         if (global == NULL)
804                 return NULL;
805
806         global->name = display->id++;
807         global->interface = interface;
808         global->data = data;
809         global->bind = bind;
810         wl_list_insert(display->global_list.prev, &global->link);
811
812         return global;
813 }
814
815 WL_EXPORT void
816 wl_display_remove_global(struct wl_display *display, struct wl_global *global)
817 {
818         struct wl_client *client;
819
820         wl_list_for_each(client, &display->client_list, link)
821                 wl_resource_post_event(client->display_resource,
822                                        WL_DISPLAY_GLOBAL_REMOVE, global->name);
823         wl_list_remove(&global->link);
824         free(global);
825 }
826
827 WL_EXPORT struct wl_event_loop *
828 wl_display_get_event_loop(struct wl_display *display)
829 {
830         return display->loop;
831 }
832
833 WL_EXPORT void
834 wl_display_terminate(struct wl_display *display)
835 {
836         display->run = 0;
837 }
838
839 WL_EXPORT void
840 wl_display_run(struct wl_display *display)
841 {
842         display->run = 1;
843
844         while (display->run)
845                 wl_event_loop_dispatch(display->loop, -1);
846 }
847
848 static int
849 socket_data(int fd, uint32_t mask, void *data)
850 {
851         struct wl_display *display = data;
852         struct sockaddr_un name;
853         socklen_t length;
854         int client_fd;
855
856         length = sizeof name;
857         client_fd =
858                 accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
859         if (client_fd < 0 && errno == ENOSYS) {
860                 client_fd = accept(fd, (struct sockaddr *) &name, &length);
861                 if (client_fd >= 0 && fcntl(client_fd, F_SETFD, FD_CLOEXEC) == -1)
862                         fprintf(stderr, "failed to set FD_CLOEXEC flag on client fd, errno: %d\n", errno);
863         }
864
865         if (client_fd < 0)
866                 fprintf(stderr, "failed to accept, errno: %d\n", errno);
867
868         wl_client_create(display, client_fd);
869
870         return 1;
871 }
872
873 static int
874 get_socket_lock(struct wl_socket *socket, socklen_t name_size)
875 {
876         struct stat socket_stat;
877         int lock_size = name_size + 5;
878
879         snprintf(socket->lock_addr, lock_size,
880                  "%s.lock", socket->addr.sun_path);
881
882         socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC,
883                                (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
884
885         if (socket->fd_lock < 0) {
886                 fprintf(stderr,
887                         "unable to open lockfile %s check permissions\n",
888                         socket->lock_addr);
889                 return -1;
890         }
891
892         if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
893                 fprintf(stderr,
894                         "unable to lock lockfile %s, maybe another compositor is running\n",
895                         socket->lock_addr);
896                 close(socket->fd_lock);
897                 return -1;
898         }
899
900         if (stat(socket->addr.sun_path, &socket_stat) < 0 ) {
901                 if (errno != ENOENT) {
902                         fprintf(stderr, "did not manage to stat file %s\n",
903                                 socket->addr.sun_path);
904                         close(socket->fd_lock);
905                         return -1;
906                 }
907         } else if (socket_stat.st_mode & S_IWUSR ||
908                    socket_stat.st_mode & S_IWGRP) {
909                 unlink(socket->addr.sun_path);
910         }
911
912         return 0;
913 }
914
915 WL_EXPORT int
916 wl_display_add_socket(struct wl_display *display, const char *name)
917 {
918         struct wl_socket *s;
919         socklen_t size, name_size;
920         const char *runtime_dir;
921
922         s = malloc(sizeof *s);
923         if (s == NULL)
924                 return -1;
925
926         s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
927         if (s->fd < 0) {
928                 free(s);
929                 return -1;
930         }
931
932         runtime_dir = getenv("XDG_RUNTIME_DIR");
933         if (runtime_dir == NULL) {
934                 runtime_dir = ".";
935                 fprintf(stderr,
936                         "XDG_RUNTIME_DIR not set, falling back to %s\n",
937                         runtime_dir);
938         }
939
940         if (name == NULL)
941                 name = getenv("WAYLAND_DISPLAY");
942         if (name == NULL)
943                 name = "wayland-0";
944
945         memset(&s->addr, 0, sizeof s->addr);
946         s->addr.sun_family = AF_LOCAL;
947         name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
948                              "%s/%s", runtime_dir, name) + 1;
949         fprintf(stderr, "using socket %s\n", s->addr.sun_path);
950
951         if (get_socket_lock(s,name_size) < 0) {
952                 close(s->fd);
953                 free(s);
954                 return -1;
955         }
956
957         size = offsetof (struct sockaddr_un, sun_path) + name_size;
958         if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
959                 close(s->fd);
960                 free(s);
961                 return -1;
962         }
963
964         if (listen(s->fd, 1) < 0) {
965                 close(s->fd);
966                 unlink(s->addr.sun_path);
967                 free(s);
968                 return -1;
969         }
970
971         s->source = wl_event_loop_add_fd(display->loop, s->fd,
972                                          WL_EVENT_READABLE,
973                                          socket_data, display);
974         if (s->source == NULL) {
975                 close(s->fd);
976                 unlink(s->addr.sun_path);
977                 free(s);
978                 return -1;
979         }
980         wl_list_insert(display->socket_list.prev, &s->link);
981
982         return 0;
983 }
984
985 WL_EXPORT struct wl_resource *
986 wl_client_add_object(struct wl_client *client,
987                      const struct wl_interface *interface,
988                      const void *implementation,
989                      uint32_t id, void *data)
990 {
991         struct wl_resource *resource;
992
993         resource = malloc(sizeof *resource);
994         if (resource == NULL) {
995                 wl_resource_post_no_memory(client->display_resource);
996                 return NULL;
997         }
998
999         resource->object.interface = interface;
1000         resource->object.implementation = implementation;
1001         resource->object.id = id;
1002         resource->client = client;
1003         resource->data = data;
1004         resource->destroy = (void *) free;
1005         wl_list_init(&resource->destroy_listener_list);
1006
1007         if (wl_map_insert_at(&client->objects, resource->object.id, resource) < 0) {
1008                 wl_resource_post_no_memory(client->display_resource);
1009                 free(resource);
1010                 return NULL;
1011         }
1012
1013         return resource;
1014 }
1015
1016 WL_EXPORT struct wl_resource *
1017 wl_client_new_object(struct wl_client *client,
1018                      const struct wl_interface *interface,
1019                      const void *implementation, void *data)
1020 {
1021         uint32_t id;
1022
1023         id = wl_map_insert_new(&client->objects, WL_MAP_SERVER_SIDE, NULL);
1024         return wl_client_add_object(client,
1025                                     interface, implementation, id, data);
1026
1027 }