xref: /aosp_15_r20/external/wayland/src/connection.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique  * Copyright © 2008 Kristian Høgsberg
3*84e872a0SLloyd Pique  * Copyright © 2013 Jason Ekstrand
4*84e872a0SLloyd Pique  *
5*84e872a0SLloyd Pique  * Permission is hereby granted, free of charge, to any person obtaining
6*84e872a0SLloyd Pique  * a copy of this software and associated documentation files (the
7*84e872a0SLloyd Pique  * "Software"), to deal in the Software without restriction, including
8*84e872a0SLloyd Pique  * without limitation the rights to use, copy, modify, merge, publish,
9*84e872a0SLloyd Pique  * distribute, sublicense, and/or sell copies of the Software, and to
10*84e872a0SLloyd Pique  * permit persons to whom the Software is furnished to do so, subject to
11*84e872a0SLloyd Pique  * the following conditions:
12*84e872a0SLloyd Pique  *
13*84e872a0SLloyd Pique  * The above copyright notice and this permission notice (including the
14*84e872a0SLloyd Pique  * next paragraph) shall be included in all copies or substantial
15*84e872a0SLloyd Pique  * portions of the Software.
16*84e872a0SLloyd Pique  *
17*84e872a0SLloyd Pique  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18*84e872a0SLloyd Pique  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*84e872a0SLloyd Pique  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*84e872a0SLloyd Pique  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21*84e872a0SLloyd Pique  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22*84e872a0SLloyd Pique  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23*84e872a0SLloyd Pique  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*84e872a0SLloyd Pique  * SOFTWARE.
25*84e872a0SLloyd Pique  */
26*84e872a0SLloyd Pique 
27*84e872a0SLloyd Pique #define _GNU_SOURCE
28*84e872a0SLloyd Pique 
29*84e872a0SLloyd Pique #include <math.h>
30*84e872a0SLloyd Pique #include <stdlib.h>
31*84e872a0SLloyd Pique #include <stdint.h>
32*84e872a0SLloyd Pique #include <string.h>
33*84e872a0SLloyd Pique #include <stdio.h>
34*84e872a0SLloyd Pique #include <errno.h>
35*84e872a0SLloyd Pique #include <sys/uio.h>
36*84e872a0SLloyd Pique #include <fcntl.h>
37*84e872a0SLloyd Pique #include <unistd.h>
38*84e872a0SLloyd Pique #include <sys/types.h>
39*84e872a0SLloyd Pique #include <sys/socket.h>
40*84e872a0SLloyd Pique #include <time.h>
41*84e872a0SLloyd Pique #include <ffi.h>
42*84e872a0SLloyd Pique 
43*84e872a0SLloyd Pique #include "wayland-util.h"
44*84e872a0SLloyd Pique #include "wayland-private.h"
45*84e872a0SLloyd Pique #include "wayland-os.h"
46*84e872a0SLloyd Pique 
47*84e872a0SLloyd Pique static inline uint32_t
div_roundup(uint32_t n,size_t a)48*84e872a0SLloyd Pique div_roundup(uint32_t n, size_t a)
49*84e872a0SLloyd Pique {
50*84e872a0SLloyd Pique 	/* The cast to uint64_t is necessary to prevent overflow when rounding
51*84e872a0SLloyd Pique 	 * values close to UINT32_MAX. After the division it is again safe to
52*84e872a0SLloyd Pique 	 * cast back to uint32_t.
53*84e872a0SLloyd Pique 	 */
54*84e872a0SLloyd Pique 	return (uint32_t) (((uint64_t) n + (a - 1)) / a);
55*84e872a0SLloyd Pique }
56*84e872a0SLloyd Pique 
57*84e872a0SLloyd Pique struct wl_ring_buffer {
58*84e872a0SLloyd Pique 	char data[4096];
59*84e872a0SLloyd Pique 	uint32_t head, tail;
60*84e872a0SLloyd Pique };
61*84e872a0SLloyd Pique 
62*84e872a0SLloyd Pique #define MASK(i) ((i) & 4095)
63*84e872a0SLloyd Pique 
64*84e872a0SLloyd Pique #define MAX_FDS_OUT	28
65*84e872a0SLloyd Pique #define CLEN		(CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
66*84e872a0SLloyd Pique 
67*84e872a0SLloyd Pique struct wl_connection {
68*84e872a0SLloyd Pique 	struct wl_ring_buffer in, out;
69*84e872a0SLloyd Pique 	struct wl_ring_buffer fds_in, fds_out;
70*84e872a0SLloyd Pique 	int fd;
71*84e872a0SLloyd Pique 	int want_flush;
72*84e872a0SLloyd Pique };
73*84e872a0SLloyd Pique 
74*84e872a0SLloyd Pique static int
ring_buffer_put(struct wl_ring_buffer * b,const void * data,size_t count)75*84e872a0SLloyd Pique ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
76*84e872a0SLloyd Pique {
77*84e872a0SLloyd Pique 	uint32_t head, size;
78*84e872a0SLloyd Pique 
79*84e872a0SLloyd Pique 	if (count > sizeof(b->data)) {
80*84e872a0SLloyd Pique 		wl_log("Data too big for buffer (%d > %d).\n",
81*84e872a0SLloyd Pique 		       count, sizeof(b->data));
82*84e872a0SLloyd Pique 		errno = E2BIG;
83*84e872a0SLloyd Pique 		return -1;
84*84e872a0SLloyd Pique 	}
85*84e872a0SLloyd Pique 
86*84e872a0SLloyd Pique 	head = MASK(b->head);
87*84e872a0SLloyd Pique 	if (head + count <= sizeof b->data) {
88*84e872a0SLloyd Pique 		memcpy(b->data + head, data, count);
89*84e872a0SLloyd Pique 	} else {
90*84e872a0SLloyd Pique 		size = sizeof b->data - head;
91*84e872a0SLloyd Pique 		memcpy(b->data + head, data, size);
92*84e872a0SLloyd Pique 		memcpy(b->data, (const char *) data + size, count - size);
93*84e872a0SLloyd Pique 	}
94*84e872a0SLloyd Pique 
95*84e872a0SLloyd Pique 	b->head += count;
96*84e872a0SLloyd Pique 
97*84e872a0SLloyd Pique 	return 0;
98*84e872a0SLloyd Pique }
99*84e872a0SLloyd Pique 
100*84e872a0SLloyd Pique static void
ring_buffer_put_iov(struct wl_ring_buffer * b,struct iovec * iov,int * count)101*84e872a0SLloyd Pique ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
102*84e872a0SLloyd Pique {
103*84e872a0SLloyd Pique 	uint32_t head, tail;
104*84e872a0SLloyd Pique 
105*84e872a0SLloyd Pique 	head = MASK(b->head);
106*84e872a0SLloyd Pique 	tail = MASK(b->tail);
107*84e872a0SLloyd Pique 	if (head < tail) {
108*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + head;
109*84e872a0SLloyd Pique 		iov[0].iov_len = tail - head;
110*84e872a0SLloyd Pique 		*count = 1;
111*84e872a0SLloyd Pique 	} else if (tail == 0) {
112*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + head;
113*84e872a0SLloyd Pique 		iov[0].iov_len = sizeof b->data - head;
114*84e872a0SLloyd Pique 		*count = 1;
115*84e872a0SLloyd Pique 	} else {
116*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + head;
117*84e872a0SLloyd Pique 		iov[0].iov_len = sizeof b->data - head;
118*84e872a0SLloyd Pique 		iov[1].iov_base = b->data;
119*84e872a0SLloyd Pique 		iov[1].iov_len = tail;
120*84e872a0SLloyd Pique 		*count = 2;
121*84e872a0SLloyd Pique 	}
122*84e872a0SLloyd Pique }
123*84e872a0SLloyd Pique 
124*84e872a0SLloyd Pique static void
ring_buffer_get_iov(struct wl_ring_buffer * b,struct iovec * iov,int * count)125*84e872a0SLloyd Pique ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
126*84e872a0SLloyd Pique {
127*84e872a0SLloyd Pique 	uint32_t head, tail;
128*84e872a0SLloyd Pique 
129*84e872a0SLloyd Pique 	head = MASK(b->head);
130*84e872a0SLloyd Pique 	tail = MASK(b->tail);
131*84e872a0SLloyd Pique 	if (tail < head) {
132*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + tail;
133*84e872a0SLloyd Pique 		iov[0].iov_len = head - tail;
134*84e872a0SLloyd Pique 		*count = 1;
135*84e872a0SLloyd Pique 	} else if (head == 0) {
136*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + tail;
137*84e872a0SLloyd Pique 		iov[0].iov_len = sizeof b->data - tail;
138*84e872a0SLloyd Pique 		*count = 1;
139*84e872a0SLloyd Pique 	} else {
140*84e872a0SLloyd Pique 		iov[0].iov_base = b->data + tail;
141*84e872a0SLloyd Pique 		iov[0].iov_len = sizeof b->data - tail;
142*84e872a0SLloyd Pique 		iov[1].iov_base = b->data;
143*84e872a0SLloyd Pique 		iov[1].iov_len = head;
144*84e872a0SLloyd Pique 		*count = 2;
145*84e872a0SLloyd Pique 	}
146*84e872a0SLloyd Pique }
147*84e872a0SLloyd Pique 
148*84e872a0SLloyd Pique static void
ring_buffer_copy(struct wl_ring_buffer * b,void * data,size_t count)149*84e872a0SLloyd Pique ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
150*84e872a0SLloyd Pique {
151*84e872a0SLloyd Pique 	uint32_t tail, size;
152*84e872a0SLloyd Pique 
153*84e872a0SLloyd Pique 	tail = MASK(b->tail);
154*84e872a0SLloyd Pique 	if (tail + count <= sizeof b->data) {
155*84e872a0SLloyd Pique 		memcpy(data, b->data + tail, count);
156*84e872a0SLloyd Pique 	} else {
157*84e872a0SLloyd Pique 		size = sizeof b->data - tail;
158*84e872a0SLloyd Pique 		memcpy(data, b->data + tail, size);
159*84e872a0SLloyd Pique 		memcpy((char *) data + size, b->data, count - size);
160*84e872a0SLloyd Pique 	}
161*84e872a0SLloyd Pique }
162*84e872a0SLloyd Pique 
163*84e872a0SLloyd Pique static uint32_t
ring_buffer_size(struct wl_ring_buffer * b)164*84e872a0SLloyd Pique ring_buffer_size(struct wl_ring_buffer *b)
165*84e872a0SLloyd Pique {
166*84e872a0SLloyd Pique 	return b->head - b->tail;
167*84e872a0SLloyd Pique }
168*84e872a0SLloyd Pique 
169*84e872a0SLloyd Pique struct wl_connection *
wl_connection_create(int fd)170*84e872a0SLloyd Pique wl_connection_create(int fd)
171*84e872a0SLloyd Pique {
172*84e872a0SLloyd Pique 	struct wl_connection *connection;
173*84e872a0SLloyd Pique 
174*84e872a0SLloyd Pique 	connection = zalloc(sizeof *connection);
175*84e872a0SLloyd Pique 	if (connection == NULL)
176*84e872a0SLloyd Pique 		return NULL;
177*84e872a0SLloyd Pique 
178*84e872a0SLloyd Pique 	connection->fd = fd;
179*84e872a0SLloyd Pique 
180*84e872a0SLloyd Pique 	return connection;
181*84e872a0SLloyd Pique }
182*84e872a0SLloyd Pique 
183*84e872a0SLloyd Pique static void
close_fds(struct wl_ring_buffer * buffer,int max)184*84e872a0SLloyd Pique close_fds(struct wl_ring_buffer *buffer, int max)
185*84e872a0SLloyd Pique {
186*84e872a0SLloyd Pique 	int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
187*84e872a0SLloyd Pique 	size_t size;
188*84e872a0SLloyd Pique 
189*84e872a0SLloyd Pique 	size = ring_buffer_size(buffer);
190*84e872a0SLloyd Pique 	if (size == 0)
191*84e872a0SLloyd Pique 		return;
192*84e872a0SLloyd Pique 
193*84e872a0SLloyd Pique 	ring_buffer_copy(buffer, fds, size);
194*84e872a0SLloyd Pique 	count = size / sizeof fds[0];
195*84e872a0SLloyd Pique 	if (max > 0 && max < count)
196*84e872a0SLloyd Pique 		count = max;
197*84e872a0SLloyd Pique 	size = count * sizeof fds[0];
198*84e872a0SLloyd Pique 	for (i = 0; i < count; i++)
199*84e872a0SLloyd Pique 		close(fds[i]);
200*84e872a0SLloyd Pique 	buffer->tail += size;
201*84e872a0SLloyd Pique }
202*84e872a0SLloyd Pique 
203*84e872a0SLloyd Pique void
wl_connection_close_fds_in(struct wl_connection * connection,int max)204*84e872a0SLloyd Pique wl_connection_close_fds_in(struct wl_connection *connection, int max)
205*84e872a0SLloyd Pique {
206*84e872a0SLloyd Pique 	close_fds(&connection->fds_in, max);
207*84e872a0SLloyd Pique }
208*84e872a0SLloyd Pique 
209*84e872a0SLloyd Pique int
wl_connection_destroy(struct wl_connection * connection)210*84e872a0SLloyd Pique wl_connection_destroy(struct wl_connection *connection)
211*84e872a0SLloyd Pique {
212*84e872a0SLloyd Pique 	int fd = connection->fd;
213*84e872a0SLloyd Pique 
214*84e872a0SLloyd Pique 	close_fds(&connection->fds_out, -1);
215*84e872a0SLloyd Pique 	close_fds(&connection->fds_in, -1);
216*84e872a0SLloyd Pique 	free(connection);
217*84e872a0SLloyd Pique 
218*84e872a0SLloyd Pique 	return fd;
219*84e872a0SLloyd Pique }
220*84e872a0SLloyd Pique 
221*84e872a0SLloyd Pique void
wl_connection_copy(struct wl_connection * connection,void * data,size_t size)222*84e872a0SLloyd Pique wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
223*84e872a0SLloyd Pique {
224*84e872a0SLloyd Pique 	ring_buffer_copy(&connection->in, data, size);
225*84e872a0SLloyd Pique }
226*84e872a0SLloyd Pique 
227*84e872a0SLloyd Pique void
wl_connection_consume(struct wl_connection * connection,size_t size)228*84e872a0SLloyd Pique wl_connection_consume(struct wl_connection *connection, size_t size)
229*84e872a0SLloyd Pique {
230*84e872a0SLloyd Pique 	connection->in.tail += size;
231*84e872a0SLloyd Pique }
232*84e872a0SLloyd Pique 
233*84e872a0SLloyd Pique static void
build_cmsg(struct wl_ring_buffer * buffer,char * data,size_t * clen)234*84e872a0SLloyd Pique build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen)
235*84e872a0SLloyd Pique {
236*84e872a0SLloyd Pique 	struct cmsghdr *cmsg;
237*84e872a0SLloyd Pique 	size_t size;
238*84e872a0SLloyd Pique 
239*84e872a0SLloyd Pique 	size = ring_buffer_size(buffer);
240*84e872a0SLloyd Pique 	if (size > MAX_FDS_OUT * sizeof(int32_t))
241*84e872a0SLloyd Pique 		size = MAX_FDS_OUT * sizeof(int32_t);
242*84e872a0SLloyd Pique 
243*84e872a0SLloyd Pique 	if (size > 0) {
244*84e872a0SLloyd Pique 		cmsg = (struct cmsghdr *) data;
245*84e872a0SLloyd Pique 		cmsg->cmsg_level = SOL_SOCKET;
246*84e872a0SLloyd Pique 		cmsg->cmsg_type = SCM_RIGHTS;
247*84e872a0SLloyd Pique 		cmsg->cmsg_len = CMSG_LEN(size);
248*84e872a0SLloyd Pique 		ring_buffer_copy(buffer, CMSG_DATA(cmsg), size);
249*84e872a0SLloyd Pique 		*clen = cmsg->cmsg_len;
250*84e872a0SLloyd Pique 	} else {
251*84e872a0SLloyd Pique 		*clen = 0;
252*84e872a0SLloyd Pique 	}
253*84e872a0SLloyd Pique }
254*84e872a0SLloyd Pique 
255*84e872a0SLloyd Pique static int
decode_cmsg(struct wl_ring_buffer * buffer,struct msghdr * msg)256*84e872a0SLloyd Pique decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
257*84e872a0SLloyd Pique {
258*84e872a0SLloyd Pique 	struct cmsghdr *cmsg;
259*84e872a0SLloyd Pique 	size_t size, max, i;
260*84e872a0SLloyd Pique 	int overflow = 0;
261*84e872a0SLloyd Pique 
262*84e872a0SLloyd Pique 	for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
263*84e872a0SLloyd Pique 	     cmsg = CMSG_NXTHDR(msg, cmsg)) {
264*84e872a0SLloyd Pique 		if (cmsg->cmsg_level != SOL_SOCKET ||
265*84e872a0SLloyd Pique 		    cmsg->cmsg_type != SCM_RIGHTS)
266*84e872a0SLloyd Pique 			continue;
267*84e872a0SLloyd Pique 
268*84e872a0SLloyd Pique 		size = cmsg->cmsg_len - CMSG_LEN(0);
269*84e872a0SLloyd Pique 		max = sizeof(buffer->data) - ring_buffer_size(buffer);
270*84e872a0SLloyd Pique 		if (size > max || overflow) {
271*84e872a0SLloyd Pique 			overflow = 1;
272*84e872a0SLloyd Pique 			size /= sizeof(int32_t);
273*84e872a0SLloyd Pique 			for (i = 0; i < size; i++)
274*84e872a0SLloyd Pique 				close(((int*)CMSG_DATA(cmsg))[i]);
275*84e872a0SLloyd Pique 		} else if (ring_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) {
276*84e872a0SLloyd Pique 				return -1;
277*84e872a0SLloyd Pique 		}
278*84e872a0SLloyd Pique 	}
279*84e872a0SLloyd Pique 
280*84e872a0SLloyd Pique 	if (overflow) {
281*84e872a0SLloyd Pique 		errno = EOVERFLOW;
282*84e872a0SLloyd Pique 		return -1;
283*84e872a0SLloyd Pique 	}
284*84e872a0SLloyd Pique 
285*84e872a0SLloyd Pique 	return 0;
286*84e872a0SLloyd Pique }
287*84e872a0SLloyd Pique 
288*84e872a0SLloyd Pique int
wl_connection_flush(struct wl_connection * connection)289*84e872a0SLloyd Pique wl_connection_flush(struct wl_connection *connection)
290*84e872a0SLloyd Pique {
291*84e872a0SLloyd Pique 	struct iovec iov[2];
292*84e872a0SLloyd Pique 	struct msghdr msg = {0};
293*84e872a0SLloyd Pique 	char cmsg[CLEN];
294*84e872a0SLloyd Pique 	int len = 0, count;
295*84e872a0SLloyd Pique 	size_t clen;
296*84e872a0SLloyd Pique 	uint32_t tail;
297*84e872a0SLloyd Pique 
298*84e872a0SLloyd Pique 	if (!connection->want_flush)
299*84e872a0SLloyd Pique 		return 0;
300*84e872a0SLloyd Pique 
301*84e872a0SLloyd Pique 	tail = connection->out.tail;
302*84e872a0SLloyd Pique 	while (connection->out.head - connection->out.tail > 0) {
303*84e872a0SLloyd Pique 		ring_buffer_get_iov(&connection->out, iov, &count);
304*84e872a0SLloyd Pique 
305*84e872a0SLloyd Pique 		build_cmsg(&connection->fds_out, cmsg, &clen);
306*84e872a0SLloyd Pique 
307*84e872a0SLloyd Pique 		msg.msg_iov = iov;
308*84e872a0SLloyd Pique 		msg.msg_iovlen = count;
309*84e872a0SLloyd Pique 		msg.msg_control = (clen > 0) ? cmsg : NULL;
310*84e872a0SLloyd Pique 		msg.msg_controllen = clen;
311*84e872a0SLloyd Pique 
312*84e872a0SLloyd Pique 		do {
313*84e872a0SLloyd Pique 			len = sendmsg(connection->fd, &msg,
314*84e872a0SLloyd Pique 				      MSG_NOSIGNAL | MSG_DONTWAIT);
315*84e872a0SLloyd Pique 		} while (len == -1 && errno == EINTR);
316*84e872a0SLloyd Pique 
317*84e872a0SLloyd Pique 		if (len == -1)
318*84e872a0SLloyd Pique 			return -1;
319*84e872a0SLloyd Pique 
320*84e872a0SLloyd Pique 		close_fds(&connection->fds_out, MAX_FDS_OUT);
321*84e872a0SLloyd Pique 
322*84e872a0SLloyd Pique 		connection->out.tail += len;
323*84e872a0SLloyd Pique 	}
324*84e872a0SLloyd Pique 
325*84e872a0SLloyd Pique 	connection->want_flush = 0;
326*84e872a0SLloyd Pique 
327*84e872a0SLloyd Pique 	return connection->out.head - tail;
328*84e872a0SLloyd Pique }
329*84e872a0SLloyd Pique 
330*84e872a0SLloyd Pique uint32_t
wl_connection_pending_input(struct wl_connection * connection)331*84e872a0SLloyd Pique wl_connection_pending_input(struct wl_connection *connection)
332*84e872a0SLloyd Pique {
333*84e872a0SLloyd Pique 	return ring_buffer_size(&connection->in);
334*84e872a0SLloyd Pique }
335*84e872a0SLloyd Pique 
336*84e872a0SLloyd Pique int
wl_connection_read(struct wl_connection * connection)337*84e872a0SLloyd Pique wl_connection_read(struct wl_connection *connection)
338*84e872a0SLloyd Pique {
339*84e872a0SLloyd Pique 	struct iovec iov[2];
340*84e872a0SLloyd Pique 	struct msghdr msg;
341*84e872a0SLloyd Pique 	char cmsg[CLEN];
342*84e872a0SLloyd Pique 	int len, count, ret;
343*84e872a0SLloyd Pique 
344*84e872a0SLloyd Pique 	if (ring_buffer_size(&connection->in) >= sizeof(connection->in.data)) {
345*84e872a0SLloyd Pique 		errno = EOVERFLOW;
346*84e872a0SLloyd Pique 		return -1;
347*84e872a0SLloyd Pique 	}
348*84e872a0SLloyd Pique 
349*84e872a0SLloyd Pique 	ring_buffer_put_iov(&connection->in, iov, &count);
350*84e872a0SLloyd Pique 
351*84e872a0SLloyd Pique 	msg.msg_name = NULL;
352*84e872a0SLloyd Pique 	msg.msg_namelen = 0;
353*84e872a0SLloyd Pique 	msg.msg_iov = iov;
354*84e872a0SLloyd Pique 	msg.msg_iovlen = count;
355*84e872a0SLloyd Pique 	msg.msg_control = cmsg;
356*84e872a0SLloyd Pique 	msg.msg_controllen = sizeof cmsg;
357*84e872a0SLloyd Pique 	msg.msg_flags = 0;
358*84e872a0SLloyd Pique 
359*84e872a0SLloyd Pique 	do {
360*84e872a0SLloyd Pique 		len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
361*84e872a0SLloyd Pique 	} while (len < 0 && errno == EINTR);
362*84e872a0SLloyd Pique 
363*84e872a0SLloyd Pique 	if (len <= 0)
364*84e872a0SLloyd Pique 		return len;
365*84e872a0SLloyd Pique 
366*84e872a0SLloyd Pique 	ret = decode_cmsg(&connection->fds_in, &msg);
367*84e872a0SLloyd Pique 	if (ret)
368*84e872a0SLloyd Pique 		return -1;
369*84e872a0SLloyd Pique 
370*84e872a0SLloyd Pique 	connection->in.head += len;
371*84e872a0SLloyd Pique 
372*84e872a0SLloyd Pique 	return wl_connection_pending_input(connection);
373*84e872a0SLloyd Pique }
374*84e872a0SLloyd Pique 
375*84e872a0SLloyd Pique int
wl_connection_write(struct wl_connection * connection,const void * data,size_t count)376*84e872a0SLloyd Pique wl_connection_write(struct wl_connection *connection,
377*84e872a0SLloyd Pique 		    const void *data, size_t count)
378*84e872a0SLloyd Pique {
379*84e872a0SLloyd Pique 	if (connection->out.head - connection->out.tail +
380*84e872a0SLloyd Pique 	    count > ARRAY_LENGTH(connection->out.data)) {
381*84e872a0SLloyd Pique 		connection->want_flush = 1;
382*84e872a0SLloyd Pique 		if (wl_connection_flush(connection) < 0)
383*84e872a0SLloyd Pique 			return -1;
384*84e872a0SLloyd Pique 	}
385*84e872a0SLloyd Pique 
386*84e872a0SLloyd Pique 	if (ring_buffer_put(&connection->out, data, count) < 0)
387*84e872a0SLloyd Pique 		return -1;
388*84e872a0SLloyd Pique 
389*84e872a0SLloyd Pique 	connection->want_flush = 1;
390*84e872a0SLloyd Pique 
391*84e872a0SLloyd Pique 	return 0;
392*84e872a0SLloyd Pique }
393*84e872a0SLloyd Pique 
394*84e872a0SLloyd Pique int
wl_connection_queue(struct wl_connection * connection,const void * data,size_t count)395*84e872a0SLloyd Pique wl_connection_queue(struct wl_connection *connection,
396*84e872a0SLloyd Pique 		    const void *data, size_t count)
397*84e872a0SLloyd Pique {
398*84e872a0SLloyd Pique 	if (connection->out.head - connection->out.tail +
399*84e872a0SLloyd Pique 	    count > ARRAY_LENGTH(connection->out.data)) {
400*84e872a0SLloyd Pique 		connection->want_flush = 1;
401*84e872a0SLloyd Pique 		if (wl_connection_flush(connection) < 0)
402*84e872a0SLloyd Pique 			return -1;
403*84e872a0SLloyd Pique 	}
404*84e872a0SLloyd Pique 
405*84e872a0SLloyd Pique 	return ring_buffer_put(&connection->out, data, count);
406*84e872a0SLloyd Pique }
407*84e872a0SLloyd Pique 
408*84e872a0SLloyd Pique int
wl_message_count_arrays(const struct wl_message * message)409*84e872a0SLloyd Pique wl_message_count_arrays(const struct wl_message *message)
410*84e872a0SLloyd Pique {
411*84e872a0SLloyd Pique 	int i, arrays;
412*84e872a0SLloyd Pique 
413*84e872a0SLloyd Pique 	for (i = 0, arrays = 0; message->signature[i]; i++) {
414*84e872a0SLloyd Pique 		if (message->signature[i] == 'a')
415*84e872a0SLloyd Pique 			arrays++;
416*84e872a0SLloyd Pique 	}
417*84e872a0SLloyd Pique 
418*84e872a0SLloyd Pique 	return arrays;
419*84e872a0SLloyd Pique }
420*84e872a0SLloyd Pique 
421*84e872a0SLloyd Pique int
wl_connection_get_fd(struct wl_connection * connection)422*84e872a0SLloyd Pique wl_connection_get_fd(struct wl_connection *connection)
423*84e872a0SLloyd Pique {
424*84e872a0SLloyd Pique 	return connection->fd;
425*84e872a0SLloyd Pique }
426*84e872a0SLloyd Pique 
427*84e872a0SLloyd Pique static int
wl_connection_put_fd(struct wl_connection * connection,int32_t fd)428*84e872a0SLloyd Pique wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
429*84e872a0SLloyd Pique {
430*84e872a0SLloyd Pique 	if (ring_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
431*84e872a0SLloyd Pique 		connection->want_flush = 1;
432*84e872a0SLloyd Pique 		if (wl_connection_flush(connection) < 0)
433*84e872a0SLloyd Pique 			return -1;
434*84e872a0SLloyd Pique 	}
435*84e872a0SLloyd Pique 
436*84e872a0SLloyd Pique 	return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
437*84e872a0SLloyd Pique }
438*84e872a0SLloyd Pique 
439*84e872a0SLloyd Pique const char *
get_next_argument(const char * signature,struct argument_details * details)440*84e872a0SLloyd Pique get_next_argument(const char *signature, struct argument_details *details)
441*84e872a0SLloyd Pique {
442*84e872a0SLloyd Pique 	details->nullable = 0;
443*84e872a0SLloyd Pique 	for(; *signature; ++signature) {
444*84e872a0SLloyd Pique 		switch(*signature) {
445*84e872a0SLloyd Pique 		case 'i':
446*84e872a0SLloyd Pique 		case 'u':
447*84e872a0SLloyd Pique 		case 'f':
448*84e872a0SLloyd Pique 		case 's':
449*84e872a0SLloyd Pique 		case 'o':
450*84e872a0SLloyd Pique 		case 'n':
451*84e872a0SLloyd Pique 		case 'a':
452*84e872a0SLloyd Pique 		case 'h':
453*84e872a0SLloyd Pique 			details->type = *signature;
454*84e872a0SLloyd Pique 			return signature + 1;
455*84e872a0SLloyd Pique 		case '?':
456*84e872a0SLloyd Pique 			details->nullable = 1;
457*84e872a0SLloyd Pique 		}
458*84e872a0SLloyd Pique 	}
459*84e872a0SLloyd Pique 	details->type = '\0';
460*84e872a0SLloyd Pique 	return signature;
461*84e872a0SLloyd Pique }
462*84e872a0SLloyd Pique 
463*84e872a0SLloyd Pique int
arg_count_for_signature(const char * signature)464*84e872a0SLloyd Pique arg_count_for_signature(const char *signature)
465*84e872a0SLloyd Pique {
466*84e872a0SLloyd Pique 	int count = 0;
467*84e872a0SLloyd Pique 	for(; *signature; ++signature) {
468*84e872a0SLloyd Pique 		switch(*signature) {
469*84e872a0SLloyd Pique 		case 'i':
470*84e872a0SLloyd Pique 		case 'u':
471*84e872a0SLloyd Pique 		case 'f':
472*84e872a0SLloyd Pique 		case 's':
473*84e872a0SLloyd Pique 		case 'o':
474*84e872a0SLloyd Pique 		case 'n':
475*84e872a0SLloyd Pique 		case 'a':
476*84e872a0SLloyd Pique 		case 'h':
477*84e872a0SLloyd Pique 			++count;
478*84e872a0SLloyd Pique 		}
479*84e872a0SLloyd Pique 	}
480*84e872a0SLloyd Pique 	return count;
481*84e872a0SLloyd Pique }
482*84e872a0SLloyd Pique 
483*84e872a0SLloyd Pique int
wl_message_get_since(const struct wl_message * message)484*84e872a0SLloyd Pique wl_message_get_since(const struct wl_message *message)
485*84e872a0SLloyd Pique {
486*84e872a0SLloyd Pique 	int since;
487*84e872a0SLloyd Pique 
488*84e872a0SLloyd Pique 	since = atoi(message->signature);
489*84e872a0SLloyd Pique 
490*84e872a0SLloyd Pique 	if (since == 0)
491*84e872a0SLloyd Pique 		since = 1;
492*84e872a0SLloyd Pique 
493*84e872a0SLloyd Pique 	return since;
494*84e872a0SLloyd Pique }
495*84e872a0SLloyd Pique 
496*84e872a0SLloyd Pique void
wl_argument_from_va_list(const char * signature,union wl_argument * args,int count,va_list ap)497*84e872a0SLloyd Pique wl_argument_from_va_list(const char *signature, union wl_argument *args,
498*84e872a0SLloyd Pique 			 int count, va_list ap)
499*84e872a0SLloyd Pique {
500*84e872a0SLloyd Pique 	int i;
501*84e872a0SLloyd Pique 	const char *sig_iter;
502*84e872a0SLloyd Pique 	struct argument_details arg;
503*84e872a0SLloyd Pique 
504*84e872a0SLloyd Pique 	sig_iter = signature;
505*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
506*84e872a0SLloyd Pique 		sig_iter = get_next_argument(sig_iter, &arg);
507*84e872a0SLloyd Pique 
508*84e872a0SLloyd Pique 		switch(arg.type) {
509*84e872a0SLloyd Pique 		case 'i':
510*84e872a0SLloyd Pique 			args[i].i = va_arg(ap, int32_t);
511*84e872a0SLloyd Pique 			break;
512*84e872a0SLloyd Pique 		case 'u':
513*84e872a0SLloyd Pique 			args[i].u = va_arg(ap, uint32_t);
514*84e872a0SLloyd Pique 			break;
515*84e872a0SLloyd Pique 		case 'f':
516*84e872a0SLloyd Pique 			args[i].f = va_arg(ap, wl_fixed_t);
517*84e872a0SLloyd Pique 			break;
518*84e872a0SLloyd Pique 		case 's':
519*84e872a0SLloyd Pique 			args[i].s = va_arg(ap, const char *);
520*84e872a0SLloyd Pique 			break;
521*84e872a0SLloyd Pique 		case 'o':
522*84e872a0SLloyd Pique 			args[i].o = va_arg(ap, struct wl_object *);
523*84e872a0SLloyd Pique 			break;
524*84e872a0SLloyd Pique 		case 'n':
525*84e872a0SLloyd Pique 			args[i].o = va_arg(ap, struct wl_object *);
526*84e872a0SLloyd Pique 			break;
527*84e872a0SLloyd Pique 		case 'a':
528*84e872a0SLloyd Pique 			args[i].a = va_arg(ap, struct wl_array *);
529*84e872a0SLloyd Pique 			break;
530*84e872a0SLloyd Pique 		case 'h':
531*84e872a0SLloyd Pique 			args[i].h = va_arg(ap, int32_t);
532*84e872a0SLloyd Pique 			break;
533*84e872a0SLloyd Pique 		case '\0':
534*84e872a0SLloyd Pique 			return;
535*84e872a0SLloyd Pique 		}
536*84e872a0SLloyd Pique 	}
537*84e872a0SLloyd Pique }
538*84e872a0SLloyd Pique 
539*84e872a0SLloyd Pique static void
wl_closure_clear_fds(struct wl_closure * closure)540*84e872a0SLloyd Pique wl_closure_clear_fds(struct wl_closure *closure)
541*84e872a0SLloyd Pique {
542*84e872a0SLloyd Pique 	const char *signature = closure->message->signature;
543*84e872a0SLloyd Pique 	struct argument_details arg;
544*84e872a0SLloyd Pique 	int i;
545*84e872a0SLloyd Pique 
546*84e872a0SLloyd Pique 	for (i = 0; i < closure->count; i++) {
547*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
548*84e872a0SLloyd Pique 		if (arg.type == 'h')
549*84e872a0SLloyd Pique 			closure->args[i].h = -1;
550*84e872a0SLloyd Pique 	}
551*84e872a0SLloyd Pique }
552*84e872a0SLloyd Pique 
553*84e872a0SLloyd Pique static struct wl_closure *
wl_closure_init(const struct wl_message * message,uint32_t size,int * num_arrays,union wl_argument * args)554*84e872a0SLloyd Pique wl_closure_init(const struct wl_message *message, uint32_t size,
555*84e872a0SLloyd Pique                 int *num_arrays, union wl_argument *args)
556*84e872a0SLloyd Pique {
557*84e872a0SLloyd Pique 	struct wl_closure *closure;
558*84e872a0SLloyd Pique 	int count;
559*84e872a0SLloyd Pique 
560*84e872a0SLloyd Pique 	count = arg_count_for_signature(message->signature);
561*84e872a0SLloyd Pique 	if (count > WL_CLOSURE_MAX_ARGS) {
562*84e872a0SLloyd Pique 		wl_log("too many args (%d)\n", count);
563*84e872a0SLloyd Pique 		errno = EINVAL;
564*84e872a0SLloyd Pique 		return NULL;
565*84e872a0SLloyd Pique 	}
566*84e872a0SLloyd Pique 
567*84e872a0SLloyd Pique 	if (size) {
568*84e872a0SLloyd Pique 		*num_arrays = wl_message_count_arrays(message);
569*84e872a0SLloyd Pique 		closure = zalloc(sizeof *closure + size +
570*84e872a0SLloyd Pique 				 *num_arrays * sizeof(struct wl_array));
571*84e872a0SLloyd Pique 	} else {
572*84e872a0SLloyd Pique 		closure = zalloc(sizeof *closure);
573*84e872a0SLloyd Pique 	}
574*84e872a0SLloyd Pique 
575*84e872a0SLloyd Pique 	if (!closure) {
576*84e872a0SLloyd Pique 		errno = ENOMEM;
577*84e872a0SLloyd Pique 		return NULL;
578*84e872a0SLloyd Pique 	}
579*84e872a0SLloyd Pique 
580*84e872a0SLloyd Pique 	if (args)
581*84e872a0SLloyd Pique 		memcpy(closure->args, args, count * sizeof *args);
582*84e872a0SLloyd Pique 
583*84e872a0SLloyd Pique 	closure->message = message;
584*84e872a0SLloyd Pique 	closure->count = count;
585*84e872a0SLloyd Pique 
586*84e872a0SLloyd Pique 	/* Set these all to -1 so we can close any that have been
587*84e872a0SLloyd Pique 	 * set to a real value during wl_closure_destroy().
588*84e872a0SLloyd Pique 	 * We may have copied a bunch of fds into the closure with
589*84e872a0SLloyd Pique 	 * memcpy previously, but those are undup()d client fds
590*84e872a0SLloyd Pique 	 * that we would have replaced anyway.
591*84e872a0SLloyd Pique 	 */
592*84e872a0SLloyd Pique 	wl_closure_clear_fds(closure);
593*84e872a0SLloyd Pique 
594*84e872a0SLloyd Pique 	return closure;
595*84e872a0SLloyd Pique }
596*84e872a0SLloyd Pique 
597*84e872a0SLloyd Pique struct wl_closure *
wl_closure_marshal(struct wl_object * sender,uint32_t opcode,union wl_argument * args,const struct wl_message * message)598*84e872a0SLloyd Pique wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
599*84e872a0SLloyd Pique 		   union wl_argument *args,
600*84e872a0SLloyd Pique 		   const struct wl_message *message)
601*84e872a0SLloyd Pique {
602*84e872a0SLloyd Pique 	struct wl_closure *closure;
603*84e872a0SLloyd Pique 	struct wl_object *object;
604*84e872a0SLloyd Pique 	int i, count, fd, dup_fd;
605*84e872a0SLloyd Pique 	const char *signature;
606*84e872a0SLloyd Pique 	struct argument_details arg;
607*84e872a0SLloyd Pique 
608*84e872a0SLloyd Pique 	closure = wl_closure_init(message, 0, NULL, args);
609*84e872a0SLloyd Pique 	if (closure == NULL)
610*84e872a0SLloyd Pique 		return NULL;
611*84e872a0SLloyd Pique 
612*84e872a0SLloyd Pique 	count = closure->count;
613*84e872a0SLloyd Pique 
614*84e872a0SLloyd Pique 	signature = message->signature;
615*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
616*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
617*84e872a0SLloyd Pique 
618*84e872a0SLloyd Pique 		switch (arg.type) {
619*84e872a0SLloyd Pique 		case 'f':
620*84e872a0SLloyd Pique 		case 'u':
621*84e872a0SLloyd Pique 		case 'i':
622*84e872a0SLloyd Pique 			break;
623*84e872a0SLloyd Pique 		case 's':
624*84e872a0SLloyd Pique 			if (!arg.nullable && args[i].s == NULL)
625*84e872a0SLloyd Pique 				goto err_null;
626*84e872a0SLloyd Pique 			break;
627*84e872a0SLloyd Pique 		case 'o':
628*84e872a0SLloyd Pique 			if (!arg.nullable && args[i].o == NULL)
629*84e872a0SLloyd Pique 				goto err_null;
630*84e872a0SLloyd Pique 			break;
631*84e872a0SLloyd Pique 		case 'n':
632*84e872a0SLloyd Pique 			object = args[i].o;
633*84e872a0SLloyd Pique 			if (object == NULL)
634*84e872a0SLloyd Pique 				goto err_null;
635*84e872a0SLloyd Pique 
636*84e872a0SLloyd Pique 			closure->args[i].n = object ? object->id : 0;
637*84e872a0SLloyd Pique 			break;
638*84e872a0SLloyd Pique 		case 'a':
639*84e872a0SLloyd Pique 			if (args[i].a == NULL)
640*84e872a0SLloyd Pique 				goto err_null;
641*84e872a0SLloyd Pique 			break;
642*84e872a0SLloyd Pique 		case 'h':
643*84e872a0SLloyd Pique 			fd = args[i].h;
644*84e872a0SLloyd Pique 			dup_fd = wl_os_dupfd_cloexec(fd, 0);
645*84e872a0SLloyd Pique 			if (dup_fd < 0) {
646*84e872a0SLloyd Pique 				wl_closure_destroy(closure);
647*84e872a0SLloyd Pique 				wl_log("error marshalling arguments for %s: dup failed: %s\n",
648*84e872a0SLloyd Pique 				       message->name, strerror(errno));
649*84e872a0SLloyd Pique 				return NULL;
650*84e872a0SLloyd Pique 			}
651*84e872a0SLloyd Pique 			closure->args[i].h = dup_fd;
652*84e872a0SLloyd Pique 			break;
653*84e872a0SLloyd Pique 		default:
654*84e872a0SLloyd Pique 			wl_abort("unhandled format code: '%c'\n", arg.type);
655*84e872a0SLloyd Pique 			break;
656*84e872a0SLloyd Pique 		}
657*84e872a0SLloyd Pique 	}
658*84e872a0SLloyd Pique 
659*84e872a0SLloyd Pique 	closure->sender_id = sender->id;
660*84e872a0SLloyd Pique 	closure->opcode = opcode;
661*84e872a0SLloyd Pique 
662*84e872a0SLloyd Pique 	return closure;
663*84e872a0SLloyd Pique 
664*84e872a0SLloyd Pique err_null:
665*84e872a0SLloyd Pique 	wl_closure_destroy(closure);
666*84e872a0SLloyd Pique 	wl_log("error marshalling arguments for %s (signature %s): "
667*84e872a0SLloyd Pique 	       "null value passed for arg %i\n", message->name,
668*84e872a0SLloyd Pique 	       message->signature, i);
669*84e872a0SLloyd Pique 	errno = EINVAL;
670*84e872a0SLloyd Pique 	return NULL;
671*84e872a0SLloyd Pique }
672*84e872a0SLloyd Pique 
673*84e872a0SLloyd Pique struct wl_closure *
wl_closure_vmarshal(struct wl_object * sender,uint32_t opcode,va_list ap,const struct wl_message * message)674*84e872a0SLloyd Pique wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap,
675*84e872a0SLloyd Pique 		    const struct wl_message *message)
676*84e872a0SLloyd Pique {
677*84e872a0SLloyd Pique 	union wl_argument args[WL_CLOSURE_MAX_ARGS];
678*84e872a0SLloyd Pique 
679*84e872a0SLloyd Pique 	wl_argument_from_va_list(message->signature, args,
680*84e872a0SLloyd Pique 				 WL_CLOSURE_MAX_ARGS, ap);
681*84e872a0SLloyd Pique 
682*84e872a0SLloyd Pique 	return wl_closure_marshal(sender, opcode, args, message);
683*84e872a0SLloyd Pique }
684*84e872a0SLloyd Pique 
685*84e872a0SLloyd Pique struct wl_closure *
wl_connection_demarshal(struct wl_connection * connection,uint32_t size,struct wl_map * objects,const struct wl_message * message)686*84e872a0SLloyd Pique wl_connection_demarshal(struct wl_connection *connection,
687*84e872a0SLloyd Pique 			uint32_t size,
688*84e872a0SLloyd Pique 			struct wl_map *objects,
689*84e872a0SLloyd Pique 			const struct wl_message *message)
690*84e872a0SLloyd Pique {
691*84e872a0SLloyd Pique 	uint32_t *p, *next, *end, length, length_in_u32, id;
692*84e872a0SLloyd Pique 	int fd;
693*84e872a0SLloyd Pique 	char *s;
694*84e872a0SLloyd Pique 	int i, count, num_arrays;
695*84e872a0SLloyd Pique 	const char *signature;
696*84e872a0SLloyd Pique 	struct argument_details arg;
697*84e872a0SLloyd Pique 	struct wl_closure *closure;
698*84e872a0SLloyd Pique 	struct wl_array *array_extra;
699*84e872a0SLloyd Pique 
700*84e872a0SLloyd Pique 	/* Space for sender_id and opcode */
701*84e872a0SLloyd Pique 	if (size < 2 * sizeof *p) {
702*84e872a0SLloyd Pique 		wl_log("message too short, invalid header\n");
703*84e872a0SLloyd Pique 		wl_connection_consume(connection, size);
704*84e872a0SLloyd Pique 		errno = EINVAL;
705*84e872a0SLloyd Pique 		return NULL;
706*84e872a0SLloyd Pique 	}
707*84e872a0SLloyd Pique 
708*84e872a0SLloyd Pique 	closure = wl_closure_init(message, size, &num_arrays, NULL);
709*84e872a0SLloyd Pique 	if (closure == NULL) {
710*84e872a0SLloyd Pique 		wl_connection_consume(connection, size);
711*84e872a0SLloyd Pique 		return NULL;
712*84e872a0SLloyd Pique 	}
713*84e872a0SLloyd Pique 
714*84e872a0SLloyd Pique 	count = closure->count;
715*84e872a0SLloyd Pique 
716*84e872a0SLloyd Pique 	array_extra = closure->extra;
717*84e872a0SLloyd Pique 	p = (uint32_t *)(closure->extra + num_arrays);
718*84e872a0SLloyd Pique 	end = p + size / sizeof *p;
719*84e872a0SLloyd Pique 
720*84e872a0SLloyd Pique 	wl_connection_copy(connection, p, size);
721*84e872a0SLloyd Pique 	closure->sender_id = *p++;
722*84e872a0SLloyd Pique 	closure->opcode = *p++ & 0x0000ffff;
723*84e872a0SLloyd Pique 
724*84e872a0SLloyd Pique 	signature = message->signature;
725*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
726*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
727*84e872a0SLloyd Pique 
728*84e872a0SLloyd Pique 		if (arg.type != 'h' && p + 1 > end) {
729*84e872a0SLloyd Pique 			wl_log("message too short, "
730*84e872a0SLloyd Pique 			       "object (%d), message %s(%s)\n",
731*84e872a0SLloyd Pique 			       closure->sender_id, message->name,
732*84e872a0SLloyd Pique 			       message->signature);
733*84e872a0SLloyd Pique 			errno = EINVAL;
734*84e872a0SLloyd Pique 			goto err;
735*84e872a0SLloyd Pique 		}
736*84e872a0SLloyd Pique 
737*84e872a0SLloyd Pique 		switch (arg.type) {
738*84e872a0SLloyd Pique 		case 'u':
739*84e872a0SLloyd Pique 			closure->args[i].u = *p++;
740*84e872a0SLloyd Pique 			break;
741*84e872a0SLloyd Pique 		case 'i':
742*84e872a0SLloyd Pique 			closure->args[i].i = *p++;
743*84e872a0SLloyd Pique 			break;
744*84e872a0SLloyd Pique 		case 'f':
745*84e872a0SLloyd Pique 			closure->args[i].f = *p++;
746*84e872a0SLloyd Pique 			break;
747*84e872a0SLloyd Pique 		case 's':
748*84e872a0SLloyd Pique 			length = *p++;
749*84e872a0SLloyd Pique 
750*84e872a0SLloyd Pique 			if (length == 0 && !arg.nullable) {
751*84e872a0SLloyd Pique 				wl_log("NULL string received on non-nullable "
752*84e872a0SLloyd Pique 				       "type, message %s(%s)\n", message->name,
753*84e872a0SLloyd Pique 				       message->signature);
754*84e872a0SLloyd Pique 				errno = EINVAL;
755*84e872a0SLloyd Pique 				goto err;
756*84e872a0SLloyd Pique 			}
757*84e872a0SLloyd Pique 			if (length == 0) {
758*84e872a0SLloyd Pique 				closure->args[i].s = NULL;
759*84e872a0SLloyd Pique 				break;
760*84e872a0SLloyd Pique 			}
761*84e872a0SLloyd Pique 
762*84e872a0SLloyd Pique 			length_in_u32 = div_roundup(length, sizeof *p);
763*84e872a0SLloyd Pique 			if ((uint32_t) (end - p) < length_in_u32) {
764*84e872a0SLloyd Pique 				wl_log("message too short, "
765*84e872a0SLloyd Pique 				       "object (%d), message %s(%s)\n",
766*84e872a0SLloyd Pique 				       closure->sender_id, message->name,
767*84e872a0SLloyd Pique 				       message->signature);
768*84e872a0SLloyd Pique 				errno = EINVAL;
769*84e872a0SLloyd Pique 				goto err;
770*84e872a0SLloyd Pique 			}
771*84e872a0SLloyd Pique 			next = p + length_in_u32;
772*84e872a0SLloyd Pique 
773*84e872a0SLloyd Pique 			s = (char *) p;
774*84e872a0SLloyd Pique 
775*84e872a0SLloyd Pique 			if (length > 0 && s[length - 1] != '\0') {
776*84e872a0SLloyd Pique 				wl_log("string not nul-terminated, "
777*84e872a0SLloyd Pique 				       "message %s(%s)\n",
778*84e872a0SLloyd Pique 				       message->name, message->signature);
779*84e872a0SLloyd Pique 				errno = EINVAL;
780*84e872a0SLloyd Pique 				goto err;
781*84e872a0SLloyd Pique 			}
782*84e872a0SLloyd Pique 
783*84e872a0SLloyd Pique 			closure->args[i].s = s;
784*84e872a0SLloyd Pique 			p = next;
785*84e872a0SLloyd Pique 			break;
786*84e872a0SLloyd Pique 		case 'o':
787*84e872a0SLloyd Pique 			id = *p++;
788*84e872a0SLloyd Pique 			closure->args[i].n = id;
789*84e872a0SLloyd Pique 
790*84e872a0SLloyd Pique 			if (id == 0 && !arg.nullable) {
791*84e872a0SLloyd Pique 				wl_log("NULL object received on non-nullable "
792*84e872a0SLloyd Pique 				       "type, message %s(%s)\n", message->name,
793*84e872a0SLloyd Pique 				       message->signature);
794*84e872a0SLloyd Pique 				errno = EINVAL;
795*84e872a0SLloyd Pique 				goto err;
796*84e872a0SLloyd Pique 			}
797*84e872a0SLloyd Pique 			break;
798*84e872a0SLloyd Pique 		case 'n':
799*84e872a0SLloyd Pique 			id = *p++;
800*84e872a0SLloyd Pique 			closure->args[i].n = id;
801*84e872a0SLloyd Pique 
802*84e872a0SLloyd Pique 			if (id == 0) {
803*84e872a0SLloyd Pique 				wl_log("NULL new ID received on non-nullable "
804*84e872a0SLloyd Pique 				       "type, message %s(%s)\n", message->name,
805*84e872a0SLloyd Pique 				       message->signature);
806*84e872a0SLloyd Pique 				errno = EINVAL;
807*84e872a0SLloyd Pique 				goto err;
808*84e872a0SLloyd Pique 			}
809*84e872a0SLloyd Pique 
810*84e872a0SLloyd Pique 			if (wl_map_reserve_new(objects, id) < 0) {
811*84e872a0SLloyd Pique 				if (errno == EINVAL) {
812*84e872a0SLloyd Pique 					wl_log("not a valid new object id (%u), "
813*84e872a0SLloyd Pique 					       "message %s(%s)\n", id,
814*84e872a0SLloyd Pique 					       message->name,
815*84e872a0SLloyd Pique 					       message->signature);
816*84e872a0SLloyd Pique 				}
817*84e872a0SLloyd Pique 				goto err;
818*84e872a0SLloyd Pique 			}
819*84e872a0SLloyd Pique 
820*84e872a0SLloyd Pique 			break;
821*84e872a0SLloyd Pique 		case 'a':
822*84e872a0SLloyd Pique 			length = *p++;
823*84e872a0SLloyd Pique 
824*84e872a0SLloyd Pique 			length_in_u32 = div_roundup(length, sizeof *p);
825*84e872a0SLloyd Pique 			if ((uint32_t) (end - p) < length_in_u32) {
826*84e872a0SLloyd Pique 				wl_log("message too short, "
827*84e872a0SLloyd Pique 				       "object (%d), message %s(%s)\n",
828*84e872a0SLloyd Pique 				       closure->sender_id, message->name,
829*84e872a0SLloyd Pique 				       message->signature);
830*84e872a0SLloyd Pique 				errno = EINVAL;
831*84e872a0SLloyd Pique 				goto err;
832*84e872a0SLloyd Pique 			}
833*84e872a0SLloyd Pique 			next = p + length_in_u32;
834*84e872a0SLloyd Pique 
835*84e872a0SLloyd Pique 			array_extra->size = length;
836*84e872a0SLloyd Pique 			array_extra->alloc = 0;
837*84e872a0SLloyd Pique 			array_extra->data = p;
838*84e872a0SLloyd Pique 
839*84e872a0SLloyd Pique 			closure->args[i].a = array_extra++;
840*84e872a0SLloyd Pique 			p = next;
841*84e872a0SLloyd Pique 			break;
842*84e872a0SLloyd Pique 		case 'h':
843*84e872a0SLloyd Pique 			if (connection->fds_in.tail == connection->fds_in.head) {
844*84e872a0SLloyd Pique 				wl_log("file descriptor expected, "
845*84e872a0SLloyd Pique 				       "object (%d), message %s(%s)\n",
846*84e872a0SLloyd Pique 				       closure->sender_id, message->name,
847*84e872a0SLloyd Pique 				       message->signature);
848*84e872a0SLloyd Pique 				errno = EINVAL;
849*84e872a0SLloyd Pique 				goto err;
850*84e872a0SLloyd Pique 			}
851*84e872a0SLloyd Pique 
852*84e872a0SLloyd Pique 			ring_buffer_copy(&connection->fds_in, &fd, sizeof fd);
853*84e872a0SLloyd Pique 			connection->fds_in.tail += sizeof fd;
854*84e872a0SLloyd Pique 			closure->args[i].h = fd;
855*84e872a0SLloyd Pique 			break;
856*84e872a0SLloyd Pique 		default:
857*84e872a0SLloyd Pique 			wl_abort("unknown type\n");
858*84e872a0SLloyd Pique 			break;
859*84e872a0SLloyd Pique 		}
860*84e872a0SLloyd Pique 	}
861*84e872a0SLloyd Pique 
862*84e872a0SLloyd Pique 	wl_connection_consume(connection, size);
863*84e872a0SLloyd Pique 
864*84e872a0SLloyd Pique 	return closure;
865*84e872a0SLloyd Pique 
866*84e872a0SLloyd Pique  err:
867*84e872a0SLloyd Pique 	wl_closure_destroy(closure);
868*84e872a0SLloyd Pique 	wl_connection_consume(connection, size);
869*84e872a0SLloyd Pique 
870*84e872a0SLloyd Pique 	return NULL;
871*84e872a0SLloyd Pique }
872*84e872a0SLloyd Pique 
873*84e872a0SLloyd Pique bool
wl_object_is_zombie(struct wl_map * map,uint32_t id)874*84e872a0SLloyd Pique wl_object_is_zombie(struct wl_map *map, uint32_t id)
875*84e872a0SLloyd Pique {
876*84e872a0SLloyd Pique 	uint32_t flags;
877*84e872a0SLloyd Pique 
878*84e872a0SLloyd Pique 	/* Zombie objects only exist on the client side. */
879*84e872a0SLloyd Pique 	if (map->side == WL_MAP_SERVER_SIDE)
880*84e872a0SLloyd Pique 		return false;
881*84e872a0SLloyd Pique 
882*84e872a0SLloyd Pique 	/* Zombie objects can only have been created by the client. */
883*84e872a0SLloyd Pique 	if (id >= WL_SERVER_ID_START)
884*84e872a0SLloyd Pique 		return false;
885*84e872a0SLloyd Pique 
886*84e872a0SLloyd Pique 	flags = wl_map_lookup_flags(map, id);
887*84e872a0SLloyd Pique 	return !!(flags & WL_MAP_ENTRY_ZOMBIE);
888*84e872a0SLloyd Pique }
889*84e872a0SLloyd Pique 
890*84e872a0SLloyd Pique int
wl_closure_lookup_objects(struct wl_closure * closure,struct wl_map * objects)891*84e872a0SLloyd Pique wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
892*84e872a0SLloyd Pique {
893*84e872a0SLloyd Pique 	struct wl_object *object;
894*84e872a0SLloyd Pique 	const struct wl_message *message;
895*84e872a0SLloyd Pique 	const char *signature;
896*84e872a0SLloyd Pique 	struct argument_details arg;
897*84e872a0SLloyd Pique 	int i, count;
898*84e872a0SLloyd Pique 	uint32_t id;
899*84e872a0SLloyd Pique 
900*84e872a0SLloyd Pique 	message = closure->message;
901*84e872a0SLloyd Pique 	signature = message->signature;
902*84e872a0SLloyd Pique 	count = arg_count_for_signature(signature);
903*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
904*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
905*84e872a0SLloyd Pique 		switch (arg.type) {
906*84e872a0SLloyd Pique 		case 'o':
907*84e872a0SLloyd Pique 			id = closure->args[i].n;
908*84e872a0SLloyd Pique 			closure->args[i].o = NULL;
909*84e872a0SLloyd Pique 
910*84e872a0SLloyd Pique 			object = wl_map_lookup(objects, id);
911*84e872a0SLloyd Pique 			if (wl_object_is_zombie(objects, id)) {
912*84e872a0SLloyd Pique 				/* references object we've already
913*84e872a0SLloyd Pique 				 * destroyed client side */
914*84e872a0SLloyd Pique 				object = NULL;
915*84e872a0SLloyd Pique 			} else if (object == NULL && id != 0) {
916*84e872a0SLloyd Pique 				wl_log("unknown object (%u), message %s(%s)\n",
917*84e872a0SLloyd Pique 				       id, message->name, message->signature);
918*84e872a0SLloyd Pique 				errno = EINVAL;
919*84e872a0SLloyd Pique 				return -1;
920*84e872a0SLloyd Pique 			}
921*84e872a0SLloyd Pique 
922*84e872a0SLloyd Pique 			if (object != NULL && message->types[i] != NULL &&
923*84e872a0SLloyd Pique 			    !wl_interface_equal((object)->interface,
924*84e872a0SLloyd Pique 						message->types[i])) {
925*84e872a0SLloyd Pique 				wl_log("invalid object (%u), type (%s), "
926*84e872a0SLloyd Pique 				       "message %s(%s)\n",
927*84e872a0SLloyd Pique 				       id, (object)->interface->name,
928*84e872a0SLloyd Pique 				       message->name, message->signature);
929*84e872a0SLloyd Pique 				errno = EINVAL;
930*84e872a0SLloyd Pique 				return -1;
931*84e872a0SLloyd Pique 			}
932*84e872a0SLloyd Pique 			closure->args[i].o = object;
933*84e872a0SLloyd Pique 		}
934*84e872a0SLloyd Pique 	}
935*84e872a0SLloyd Pique 
936*84e872a0SLloyd Pique 	return 0;
937*84e872a0SLloyd Pique }
938*84e872a0SLloyd Pique 
939*84e872a0SLloyd Pique static void
convert_arguments_to_ffi(const char * signature,uint32_t flags,union wl_argument * args,int count,ffi_type ** ffi_types,void ** ffi_args)940*84e872a0SLloyd Pique convert_arguments_to_ffi(const char *signature, uint32_t flags,
941*84e872a0SLloyd Pique 			 union wl_argument *args,
942*84e872a0SLloyd Pique 			 int count, ffi_type **ffi_types, void** ffi_args)
943*84e872a0SLloyd Pique {
944*84e872a0SLloyd Pique 	int i;
945*84e872a0SLloyd Pique 	const char *sig_iter;
946*84e872a0SLloyd Pique 	struct argument_details arg;
947*84e872a0SLloyd Pique 
948*84e872a0SLloyd Pique 	sig_iter = signature;
949*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
950*84e872a0SLloyd Pique 		sig_iter = get_next_argument(sig_iter, &arg);
951*84e872a0SLloyd Pique 
952*84e872a0SLloyd Pique 		switch(arg.type) {
953*84e872a0SLloyd Pique 		case 'i':
954*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_sint32;
955*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].i;
956*84e872a0SLloyd Pique 			break;
957*84e872a0SLloyd Pique 		case 'u':
958*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_uint32;
959*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].u;
960*84e872a0SLloyd Pique 			break;
961*84e872a0SLloyd Pique 		case 'f':
962*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_sint32;
963*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].f;
964*84e872a0SLloyd Pique 			break;
965*84e872a0SLloyd Pique 		case 's':
966*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_pointer;
967*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].s;
968*84e872a0SLloyd Pique 			break;
969*84e872a0SLloyd Pique 		case 'o':
970*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_pointer;
971*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].o;
972*84e872a0SLloyd Pique 			break;
973*84e872a0SLloyd Pique 		case 'n':
974*84e872a0SLloyd Pique 			if (flags & WL_CLOSURE_INVOKE_CLIENT) {
975*84e872a0SLloyd Pique 				ffi_types[i] = &ffi_type_pointer;
976*84e872a0SLloyd Pique 				ffi_args[i] = &args[i].o;
977*84e872a0SLloyd Pique 			} else {
978*84e872a0SLloyd Pique 				ffi_types[i] = &ffi_type_uint32;
979*84e872a0SLloyd Pique 				ffi_args[i] = &args[i].n;
980*84e872a0SLloyd Pique 			}
981*84e872a0SLloyd Pique 			break;
982*84e872a0SLloyd Pique 		case 'a':
983*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_pointer;
984*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].a;
985*84e872a0SLloyd Pique 			break;
986*84e872a0SLloyd Pique 		case 'h':
987*84e872a0SLloyd Pique 			ffi_types[i] = &ffi_type_sint32;
988*84e872a0SLloyd Pique 			ffi_args[i] = &args[i].h;
989*84e872a0SLloyd Pique 			break;
990*84e872a0SLloyd Pique 		default:
991*84e872a0SLloyd Pique 			wl_abort("unknown type\n");
992*84e872a0SLloyd Pique 			break;
993*84e872a0SLloyd Pique 		}
994*84e872a0SLloyd Pique 	}
995*84e872a0SLloyd Pique }
996*84e872a0SLloyd Pique 
997*84e872a0SLloyd Pique void
wl_closure_invoke(struct wl_closure * closure,uint32_t flags,struct wl_object * target,uint32_t opcode,void * data)998*84e872a0SLloyd Pique wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
999*84e872a0SLloyd Pique 		  struct wl_object *target, uint32_t opcode, void *data)
1000*84e872a0SLloyd Pique {
1001*84e872a0SLloyd Pique 	int count;
1002*84e872a0SLloyd Pique 	ffi_cif cif;
1003*84e872a0SLloyd Pique 	ffi_type *ffi_types[WL_CLOSURE_MAX_ARGS + 2];
1004*84e872a0SLloyd Pique 	void * ffi_args[WL_CLOSURE_MAX_ARGS + 2];
1005*84e872a0SLloyd Pique 	void (* const *implementation)(void);
1006*84e872a0SLloyd Pique 
1007*84e872a0SLloyd Pique 	count = arg_count_for_signature(closure->message->signature);
1008*84e872a0SLloyd Pique 
1009*84e872a0SLloyd Pique 	ffi_types[0] = &ffi_type_pointer;
1010*84e872a0SLloyd Pique 	ffi_args[0] = &data;
1011*84e872a0SLloyd Pique 	ffi_types[1] = &ffi_type_pointer;
1012*84e872a0SLloyd Pique 	ffi_args[1] = &target;
1013*84e872a0SLloyd Pique 
1014*84e872a0SLloyd Pique 	convert_arguments_to_ffi(closure->message->signature, flags, closure->args,
1015*84e872a0SLloyd Pique 				 count, ffi_types + 2, ffi_args + 2);
1016*84e872a0SLloyd Pique 
1017*84e872a0SLloyd Pique 	ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
1018*84e872a0SLloyd Pique 		     count + 2, &ffi_type_void, ffi_types);
1019*84e872a0SLloyd Pique 
1020*84e872a0SLloyd Pique 	implementation = target->implementation;
1021*84e872a0SLloyd Pique 	if (!implementation[opcode]) {
1022*84e872a0SLloyd Pique 		wl_abort("listener function for opcode %u of %s is NULL\n",
1023*84e872a0SLloyd Pique 			 opcode, target->interface->name);
1024*84e872a0SLloyd Pique 	}
1025*84e872a0SLloyd Pique 	ffi_call(&cif, implementation[opcode], NULL, ffi_args);
1026*84e872a0SLloyd Pique 
1027*84e872a0SLloyd Pique 	wl_closure_clear_fds(closure);
1028*84e872a0SLloyd Pique }
1029*84e872a0SLloyd Pique 
1030*84e872a0SLloyd Pique void
wl_closure_dispatch(struct wl_closure * closure,wl_dispatcher_func_t dispatcher,struct wl_object * target,uint32_t opcode)1031*84e872a0SLloyd Pique wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
1032*84e872a0SLloyd Pique 		    struct wl_object *target, uint32_t opcode)
1033*84e872a0SLloyd Pique {
1034*84e872a0SLloyd Pique 	dispatcher(target->implementation, target, opcode, closure->message,
1035*84e872a0SLloyd Pique 		   closure->args);
1036*84e872a0SLloyd Pique 
1037*84e872a0SLloyd Pique 	wl_closure_clear_fds(closure);
1038*84e872a0SLloyd Pique }
1039*84e872a0SLloyd Pique 
1040*84e872a0SLloyd Pique static int
copy_fds_to_connection(struct wl_closure * closure,struct wl_connection * connection)1041*84e872a0SLloyd Pique copy_fds_to_connection(struct wl_closure *closure,
1042*84e872a0SLloyd Pique 		       struct wl_connection *connection)
1043*84e872a0SLloyd Pique {
1044*84e872a0SLloyd Pique 	const struct wl_message *message = closure->message;
1045*84e872a0SLloyd Pique 	uint32_t i, count;
1046*84e872a0SLloyd Pique 	struct argument_details arg;
1047*84e872a0SLloyd Pique 	const char *signature = message->signature;
1048*84e872a0SLloyd Pique 	int fd;
1049*84e872a0SLloyd Pique 
1050*84e872a0SLloyd Pique 	count = arg_count_for_signature(signature);
1051*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
1052*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
1053*84e872a0SLloyd Pique 		if (arg.type != 'h')
1054*84e872a0SLloyd Pique 			continue;
1055*84e872a0SLloyd Pique 
1056*84e872a0SLloyd Pique 		fd = closure->args[i].h;
1057*84e872a0SLloyd Pique 		if (wl_connection_put_fd(connection, fd)) {
1058*84e872a0SLloyd Pique 			wl_log("request could not be marshaled: "
1059*84e872a0SLloyd Pique 			       "can't send file descriptor\n");
1060*84e872a0SLloyd Pique 			return -1;
1061*84e872a0SLloyd Pique 		}
1062*84e872a0SLloyd Pique 		closure->args[i].h = -1;
1063*84e872a0SLloyd Pique 	}
1064*84e872a0SLloyd Pique 
1065*84e872a0SLloyd Pique 	return 0;
1066*84e872a0SLloyd Pique }
1067*84e872a0SLloyd Pique 
1068*84e872a0SLloyd Pique 
1069*84e872a0SLloyd Pique static uint32_t
buffer_size_for_closure(struct wl_closure * closure)1070*84e872a0SLloyd Pique buffer_size_for_closure(struct wl_closure *closure)
1071*84e872a0SLloyd Pique {
1072*84e872a0SLloyd Pique 	const struct wl_message *message = closure->message;
1073*84e872a0SLloyd Pique 	int i, count;
1074*84e872a0SLloyd Pique 	struct argument_details arg;
1075*84e872a0SLloyd Pique 	const char *signature;
1076*84e872a0SLloyd Pique 	uint32_t size, buffer_size = 0;
1077*84e872a0SLloyd Pique 
1078*84e872a0SLloyd Pique 	signature = message->signature;
1079*84e872a0SLloyd Pique 	count = arg_count_for_signature(signature);
1080*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
1081*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
1082*84e872a0SLloyd Pique 
1083*84e872a0SLloyd Pique 		switch (arg.type) {
1084*84e872a0SLloyd Pique 		case 'h':
1085*84e872a0SLloyd Pique 			break;
1086*84e872a0SLloyd Pique 		case 'u':
1087*84e872a0SLloyd Pique 		case 'i':
1088*84e872a0SLloyd Pique 		case 'f':
1089*84e872a0SLloyd Pique 		case 'o':
1090*84e872a0SLloyd Pique 		case 'n':
1091*84e872a0SLloyd Pique 			buffer_size++;
1092*84e872a0SLloyd Pique 			break;
1093*84e872a0SLloyd Pique 		case 's':
1094*84e872a0SLloyd Pique 			if (closure->args[i].s == NULL) {
1095*84e872a0SLloyd Pique 				buffer_size++;
1096*84e872a0SLloyd Pique 				break;
1097*84e872a0SLloyd Pique 			}
1098*84e872a0SLloyd Pique 
1099*84e872a0SLloyd Pique 			size = strlen(closure->args[i].s) + 1;
1100*84e872a0SLloyd Pique 			buffer_size += 1 + div_roundup(size, sizeof(uint32_t));
1101*84e872a0SLloyd Pique 			break;
1102*84e872a0SLloyd Pique 		case 'a':
1103*84e872a0SLloyd Pique 			if (closure->args[i].a == NULL) {
1104*84e872a0SLloyd Pique 				buffer_size++;
1105*84e872a0SLloyd Pique 				break;
1106*84e872a0SLloyd Pique 			}
1107*84e872a0SLloyd Pique 
1108*84e872a0SLloyd Pique 			size = closure->args[i].a->size;
1109*84e872a0SLloyd Pique 			buffer_size += (1 + div_roundup(size, sizeof(uint32_t)));
1110*84e872a0SLloyd Pique 			break;
1111*84e872a0SLloyd Pique 		default:
1112*84e872a0SLloyd Pique 			break;
1113*84e872a0SLloyd Pique 		}
1114*84e872a0SLloyd Pique 	}
1115*84e872a0SLloyd Pique 
1116*84e872a0SLloyd Pique 	return buffer_size + 2;
1117*84e872a0SLloyd Pique }
1118*84e872a0SLloyd Pique 
1119*84e872a0SLloyd Pique static int
serialize_closure(struct wl_closure * closure,uint32_t * buffer,size_t buffer_count)1120*84e872a0SLloyd Pique serialize_closure(struct wl_closure *closure, uint32_t *buffer,
1121*84e872a0SLloyd Pique 		  size_t buffer_count)
1122*84e872a0SLloyd Pique {
1123*84e872a0SLloyd Pique 	const struct wl_message *message = closure->message;
1124*84e872a0SLloyd Pique 	unsigned int i, count, size;
1125*84e872a0SLloyd Pique 	uint32_t *p, *end;
1126*84e872a0SLloyd Pique 	struct argument_details arg;
1127*84e872a0SLloyd Pique 	const char *signature;
1128*84e872a0SLloyd Pique 
1129*84e872a0SLloyd Pique 	if (buffer_count < 2)
1130*84e872a0SLloyd Pique 		goto overflow;
1131*84e872a0SLloyd Pique 
1132*84e872a0SLloyd Pique 	p = buffer + 2;
1133*84e872a0SLloyd Pique 	end = buffer + buffer_count;
1134*84e872a0SLloyd Pique 
1135*84e872a0SLloyd Pique 	signature = message->signature;
1136*84e872a0SLloyd Pique 	count = arg_count_for_signature(signature);
1137*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
1138*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
1139*84e872a0SLloyd Pique 
1140*84e872a0SLloyd Pique 		if (arg.type == 'h')
1141*84e872a0SLloyd Pique 			continue;
1142*84e872a0SLloyd Pique 
1143*84e872a0SLloyd Pique 		if (p + 1 > end)
1144*84e872a0SLloyd Pique 			goto overflow;
1145*84e872a0SLloyd Pique 
1146*84e872a0SLloyd Pique 		switch (arg.type) {
1147*84e872a0SLloyd Pique 		case 'u':
1148*84e872a0SLloyd Pique 			*p++ = closure->args[i].u;
1149*84e872a0SLloyd Pique 			break;
1150*84e872a0SLloyd Pique 		case 'i':
1151*84e872a0SLloyd Pique 			*p++ = closure->args[i].i;
1152*84e872a0SLloyd Pique 			break;
1153*84e872a0SLloyd Pique 		case 'f':
1154*84e872a0SLloyd Pique 			*p++ = closure->args[i].f;
1155*84e872a0SLloyd Pique 			break;
1156*84e872a0SLloyd Pique 		case 'o':
1157*84e872a0SLloyd Pique 			*p++ = closure->args[i].o ? closure->args[i].o->id : 0;
1158*84e872a0SLloyd Pique 			break;
1159*84e872a0SLloyd Pique 		case 'n':
1160*84e872a0SLloyd Pique 			*p++ = closure->args[i].n;
1161*84e872a0SLloyd Pique 			break;
1162*84e872a0SLloyd Pique 		case 's':
1163*84e872a0SLloyd Pique 			if (closure->args[i].s == NULL) {
1164*84e872a0SLloyd Pique 				*p++ = 0;
1165*84e872a0SLloyd Pique 				break;
1166*84e872a0SLloyd Pique 			}
1167*84e872a0SLloyd Pique 
1168*84e872a0SLloyd Pique 			size = strlen(closure->args[i].s) + 1;
1169*84e872a0SLloyd Pique 			*p++ = size;
1170*84e872a0SLloyd Pique 
1171*84e872a0SLloyd Pique 			if (p + div_roundup(size, sizeof *p) > end)
1172*84e872a0SLloyd Pique 				goto overflow;
1173*84e872a0SLloyd Pique 
1174*84e872a0SLloyd Pique 			memcpy(p, closure->args[i].s, size);
1175*84e872a0SLloyd Pique 			p += div_roundup(size, sizeof *p);
1176*84e872a0SLloyd Pique 			break;
1177*84e872a0SLloyd Pique 		case 'a':
1178*84e872a0SLloyd Pique 			if (closure->args[i].a == NULL) {
1179*84e872a0SLloyd Pique 				*p++ = 0;
1180*84e872a0SLloyd Pique 				break;
1181*84e872a0SLloyd Pique 			}
1182*84e872a0SLloyd Pique 
1183*84e872a0SLloyd Pique 			size = closure->args[i].a->size;
1184*84e872a0SLloyd Pique 			*p++ = size;
1185*84e872a0SLloyd Pique 
1186*84e872a0SLloyd Pique 			if (p + div_roundup(size, sizeof *p) > end)
1187*84e872a0SLloyd Pique 				goto overflow;
1188*84e872a0SLloyd Pique 
1189*84e872a0SLloyd Pique 			memcpy(p, closure->args[i].a->data, size);
1190*84e872a0SLloyd Pique 			p += div_roundup(size, sizeof *p);
1191*84e872a0SLloyd Pique 			break;
1192*84e872a0SLloyd Pique 		default:
1193*84e872a0SLloyd Pique 			break;
1194*84e872a0SLloyd Pique 		}
1195*84e872a0SLloyd Pique 	}
1196*84e872a0SLloyd Pique 
1197*84e872a0SLloyd Pique 	size = (p - buffer) * sizeof *p;
1198*84e872a0SLloyd Pique 
1199*84e872a0SLloyd Pique 	buffer[0] = closure->sender_id;
1200*84e872a0SLloyd Pique 	buffer[1] = size << 16 | (closure->opcode & 0x0000ffff);
1201*84e872a0SLloyd Pique 
1202*84e872a0SLloyd Pique 	return size;
1203*84e872a0SLloyd Pique 
1204*84e872a0SLloyd Pique overflow:
1205*84e872a0SLloyd Pique 	errno = ERANGE;
1206*84e872a0SLloyd Pique 	return -1;
1207*84e872a0SLloyd Pique }
1208*84e872a0SLloyd Pique 
1209*84e872a0SLloyd Pique int
wl_closure_send(struct wl_closure * closure,struct wl_connection * connection)1210*84e872a0SLloyd Pique wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
1211*84e872a0SLloyd Pique {
1212*84e872a0SLloyd Pique 	int size;
1213*84e872a0SLloyd Pique 	uint32_t buffer_size;
1214*84e872a0SLloyd Pique 	uint32_t *buffer;
1215*84e872a0SLloyd Pique 	int result;
1216*84e872a0SLloyd Pique 
1217*84e872a0SLloyd Pique 	if (copy_fds_to_connection(closure, connection))
1218*84e872a0SLloyd Pique 		return -1;
1219*84e872a0SLloyd Pique 
1220*84e872a0SLloyd Pique 	buffer_size = buffer_size_for_closure(closure);
1221*84e872a0SLloyd Pique 	buffer = zalloc(buffer_size * sizeof buffer[0]);
1222*84e872a0SLloyd Pique 	if (buffer == NULL)
1223*84e872a0SLloyd Pique 		return -1;
1224*84e872a0SLloyd Pique 
1225*84e872a0SLloyd Pique 	size = serialize_closure(closure, buffer, buffer_size);
1226*84e872a0SLloyd Pique 	if (size < 0) {
1227*84e872a0SLloyd Pique 		free(buffer);
1228*84e872a0SLloyd Pique 		return -1;
1229*84e872a0SLloyd Pique 	}
1230*84e872a0SLloyd Pique 
1231*84e872a0SLloyd Pique 	result = wl_connection_write(connection, buffer, size);
1232*84e872a0SLloyd Pique 	free(buffer);
1233*84e872a0SLloyd Pique 
1234*84e872a0SLloyd Pique 	return result;
1235*84e872a0SLloyd Pique }
1236*84e872a0SLloyd Pique 
1237*84e872a0SLloyd Pique int
wl_closure_queue(struct wl_closure * closure,struct wl_connection * connection)1238*84e872a0SLloyd Pique wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
1239*84e872a0SLloyd Pique {
1240*84e872a0SLloyd Pique 	int size;
1241*84e872a0SLloyd Pique 	uint32_t buffer_size;
1242*84e872a0SLloyd Pique 	uint32_t *buffer;
1243*84e872a0SLloyd Pique 	int result;
1244*84e872a0SLloyd Pique 
1245*84e872a0SLloyd Pique 	if (copy_fds_to_connection(closure, connection))
1246*84e872a0SLloyd Pique 		return -1;
1247*84e872a0SLloyd Pique 
1248*84e872a0SLloyd Pique 	buffer_size = buffer_size_for_closure(closure);
1249*84e872a0SLloyd Pique 	buffer = malloc(buffer_size * sizeof buffer[0]);
1250*84e872a0SLloyd Pique 	if (buffer == NULL)
1251*84e872a0SLloyd Pique 		return -1;
1252*84e872a0SLloyd Pique 
1253*84e872a0SLloyd Pique 	size = serialize_closure(closure, buffer, buffer_size);
1254*84e872a0SLloyd Pique 	if (size < 0) {
1255*84e872a0SLloyd Pique 		free(buffer);
1256*84e872a0SLloyd Pique 		return -1;
1257*84e872a0SLloyd Pique 	}
1258*84e872a0SLloyd Pique 
1259*84e872a0SLloyd Pique 	result = wl_connection_queue(connection, buffer, size);
1260*84e872a0SLloyd Pique 	free(buffer);
1261*84e872a0SLloyd Pique 
1262*84e872a0SLloyd Pique 	return result;
1263*84e872a0SLloyd Pique }
1264*84e872a0SLloyd Pique 
1265*84e872a0SLloyd Pique void
wl_closure_print(struct wl_closure * closure,struct wl_object * target,bool send,const char * discarded_reason)1266*84e872a0SLloyd Pique wl_closure_print(struct wl_closure *closure, struct wl_object *target,
1267*84e872a0SLloyd Pique 		 bool send, const char *discarded_reason)
1268*84e872a0SLloyd Pique {
1269*84e872a0SLloyd Pique 	int i;
1270*84e872a0SLloyd Pique 	struct argument_details arg;
1271*84e872a0SLloyd Pique 	const char *signature = closure->message->signature;
1272*84e872a0SLloyd Pique 	struct timespec tp;
1273*84e872a0SLloyd Pique 	unsigned int time;
1274*84e872a0SLloyd Pique 	uint32_t nval;
1275*84e872a0SLloyd Pique 	FILE *f;
1276*84e872a0SLloyd Pique 	char *buffer;
1277*84e872a0SLloyd Pique 	size_t buffer_length;
1278*84e872a0SLloyd Pique 
1279*84e872a0SLloyd Pique 	f = open_memstream(&buffer, &buffer_length);
1280*84e872a0SLloyd Pique 	if (f == NULL)
1281*84e872a0SLloyd Pique 		return;
1282*84e872a0SLloyd Pique 
1283*84e872a0SLloyd Pique 	clock_gettime(CLOCK_REALTIME, &tp);
1284*84e872a0SLloyd Pique 	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
1285*84e872a0SLloyd Pique 
1286*84e872a0SLloyd Pique 	fprintf(f, "[%7u.%03u] %s%s%s%s%s@%u.%s(",
1287*84e872a0SLloyd Pique 		time / 1000, time % 1000,
1288*84e872a0SLloyd Pique 		(discarded_reason != NULL) ? "discarded[" : "",
1289*84e872a0SLloyd Pique 		(discarded_reason != NULL) ? discarded_reason : "",
1290*84e872a0SLloyd Pique 		(discarded_reason != NULL) ? "] " : "",
1291*84e872a0SLloyd Pique 		send ? " -> " : "",
1292*84e872a0SLloyd Pique 		target->interface->name, target->id,
1293*84e872a0SLloyd Pique 		closure->message->name);
1294*84e872a0SLloyd Pique 
1295*84e872a0SLloyd Pique 	for (i = 0; i < closure->count; i++) {
1296*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
1297*84e872a0SLloyd Pique 		if (i > 0)
1298*84e872a0SLloyd Pique 			fprintf(f, ", ");
1299*84e872a0SLloyd Pique 
1300*84e872a0SLloyd Pique 		switch (arg.type) {
1301*84e872a0SLloyd Pique 		case 'u':
1302*84e872a0SLloyd Pique 			fprintf(f, "%u", closure->args[i].u);
1303*84e872a0SLloyd Pique 			break;
1304*84e872a0SLloyd Pique 		case 'i':
1305*84e872a0SLloyd Pique 			fprintf(f, "%d", closure->args[i].i);
1306*84e872a0SLloyd Pique 			break;
1307*84e872a0SLloyd Pique 		case 'f':
1308*84e872a0SLloyd Pique 			/* The magic number 390625 is 1e8 / 256 */
1309*84e872a0SLloyd Pique 			if (closure->args[i].f >= 0) {
1310*84e872a0SLloyd Pique 				fprintf(f, "%d.%08d",
1311*84e872a0SLloyd Pique 					closure->args[i].f / 256,
1312*84e872a0SLloyd Pique 					390625 * (closure->args[i].f % 256));
1313*84e872a0SLloyd Pique 			} else {
1314*84e872a0SLloyd Pique 
1315*84e872a0SLloyd Pique 				fprintf(f, "-%d.%08d",
1316*84e872a0SLloyd Pique 					closure->args[i].f / -256,
1317*84e872a0SLloyd Pique 					-390625 * (closure->args[i].f % 256));
1318*84e872a0SLloyd Pique 			}
1319*84e872a0SLloyd Pique 			break;
1320*84e872a0SLloyd Pique 		case 's':
1321*84e872a0SLloyd Pique 			if (closure->args[i].s)
1322*84e872a0SLloyd Pique 				fprintf(f, "\"%s\"", closure->args[i].s);
1323*84e872a0SLloyd Pique 			else
1324*84e872a0SLloyd Pique 				fprintf(f, "nil");
1325*84e872a0SLloyd Pique 			break;
1326*84e872a0SLloyd Pique 		case 'o':
1327*84e872a0SLloyd Pique 			if (closure->args[i].o)
1328*84e872a0SLloyd Pique 				fprintf(f, "%s@%u",
1329*84e872a0SLloyd Pique 					closure->args[i].o->interface->name,
1330*84e872a0SLloyd Pique 					closure->args[i].o->id);
1331*84e872a0SLloyd Pique 			else
1332*84e872a0SLloyd Pique 				fprintf(f, "nil");
1333*84e872a0SLloyd Pique 			break;
1334*84e872a0SLloyd Pique 		case 'n':
1335*84e872a0SLloyd Pique 			nval = closure->args[i].n;
1336*84e872a0SLloyd Pique 
1337*84e872a0SLloyd Pique 			fprintf(f, "new id %s@",
1338*84e872a0SLloyd Pique 				(closure->message->types[i]) ?
1339*84e872a0SLloyd Pique 				 closure->message->types[i]->name :
1340*84e872a0SLloyd Pique 				  "[unknown]");
1341*84e872a0SLloyd Pique 			if (nval != 0)
1342*84e872a0SLloyd Pique 				fprintf(f, "%u", nval);
1343*84e872a0SLloyd Pique 			else
1344*84e872a0SLloyd Pique 				fprintf(f, "nil");
1345*84e872a0SLloyd Pique 			break;
1346*84e872a0SLloyd Pique 		case 'a':
1347*84e872a0SLloyd Pique 			fprintf(f, "array[%zu]", closure->args[i].a->size);
1348*84e872a0SLloyd Pique 			break;
1349*84e872a0SLloyd Pique 		case 'h':
1350*84e872a0SLloyd Pique 			fprintf(f, "fd %d", closure->args[i].h);
1351*84e872a0SLloyd Pique 			break;
1352*84e872a0SLloyd Pique 		}
1353*84e872a0SLloyd Pique 	}
1354*84e872a0SLloyd Pique 
1355*84e872a0SLloyd Pique 	fprintf(f, ")\n");
1356*84e872a0SLloyd Pique 
1357*84e872a0SLloyd Pique 	if (fclose(f) == 0) {
1358*84e872a0SLloyd Pique 		fprintf(stderr, "%s", buffer);
1359*84e872a0SLloyd Pique 		free(buffer);
1360*84e872a0SLloyd Pique 	}
1361*84e872a0SLloyd Pique }
1362*84e872a0SLloyd Pique 
1363*84e872a0SLloyd Pique static int
wl_closure_close_fds(struct wl_closure * closure)1364*84e872a0SLloyd Pique wl_closure_close_fds(struct wl_closure *closure)
1365*84e872a0SLloyd Pique {
1366*84e872a0SLloyd Pique 	int i;
1367*84e872a0SLloyd Pique 	struct argument_details arg;
1368*84e872a0SLloyd Pique 	const char *signature = closure->message->signature;
1369*84e872a0SLloyd Pique 
1370*84e872a0SLloyd Pique 	for (i = 0; i < closure->count; i++) {
1371*84e872a0SLloyd Pique 		signature = get_next_argument(signature, &arg);
1372*84e872a0SLloyd Pique 		if (arg.type == 'h' && closure->args[i].h != -1)
1373*84e872a0SLloyd Pique 			close(closure->args[i].h);
1374*84e872a0SLloyd Pique 	}
1375*84e872a0SLloyd Pique 
1376*84e872a0SLloyd Pique 	return 0;
1377*84e872a0SLloyd Pique }
1378*84e872a0SLloyd Pique 
1379*84e872a0SLloyd Pique void
wl_closure_destroy(struct wl_closure * closure)1380*84e872a0SLloyd Pique wl_closure_destroy(struct wl_closure *closure)
1381*84e872a0SLloyd Pique {
1382*84e872a0SLloyd Pique 	/* wl_closure_destroy has free() semantics */
1383*84e872a0SLloyd Pique 	if (!closure)
1384*84e872a0SLloyd Pique 		return;
1385*84e872a0SLloyd Pique 
1386*84e872a0SLloyd Pique 	wl_closure_close_fds(closure);
1387*84e872a0SLloyd Pique 	free(closure);
1388*84e872a0SLloyd Pique }
1389