fork
Configure Feed
Select the types of activity you want to include in your feed.
The open source OpenXR runtime
fork
Configure Feed
Select the types of activity you want to include in your feed.
1// Copyright 2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief IPC util helpers, for internal use only
6 * @author Ryan Pavlik <ryan.pavlik@collabora.com>
7 * @author Pete Black <pblack@collabora.com>
8 * @author Jakob Bornecrantz <jakob@collabora.com>
9 * @ingroup ipc_shared
10 */
11
12#include "xrt/xrt_config_os.h"
13
14#include "shared/ipc_utils.h"
15#include "shared/ipc_protocol.h"
16
17#include <errno.h>
18#include <sys/socket.h>
19#include <unistd.h>
20
21#include <stdio.h>
22#include <string.h>
23#include <stdint.h>
24#include <assert.h>
25
26#include "util/u_logging.h"
27
28/*
29 *
30 * Logging
31 *
32 */
33
34#define IPC_TRACE(d, ...) U_LOG_IFL_T(d->ll, __VA_ARGS__)
35#define IPC_DEBUG(d, ...) U_LOG_IFL_D(d->ll, __VA_ARGS__)
36#define IPC_INFO(d, ...) U_LOG_IFL_I(d->ll, __VA_ARGS__)
37#define IPC_WARN(d, ...) U_LOG_IFL_W(d->ll, __VA_ARGS__)
38#define IPC_ERROR(d, ...) U_LOG_IFL_E(d->ll, __VA_ARGS__)
39
40void
41ipc_message_channel_close(struct ipc_message_channel *imc)
42{
43 if (imc->socket_fd < 0) {
44 return;
45 }
46 close(imc->socket_fd);
47 imc->socket_fd = -1;
48}
49
50xrt_result_t
51ipc_send(struct ipc_message_channel *imc, const void *data, size_t size)
52{
53 struct msghdr msg = {0};
54 struct iovec iov = {0};
55
56 iov.iov_base = (void *)data;
57 iov.iov_len = size;
58
59 msg.msg_name = NULL;
60 msg.msg_namelen = 0;
61 msg.msg_iov = &iov;
62 msg.msg_iovlen = 1;
63 msg.msg_flags = 0;
64
65 ssize_t ret = sendmsg(imc->socket_fd, &msg, MSG_NOSIGNAL);
66 if (ret < 0) {
67 int code = errno;
68 IPC_ERROR(imc, "ERROR: Sending plain message on socket %d failed with error: '%i' '%s'!",
69 (int)imc->socket_fd, code, strerror(code));
70 return XRT_ERROR_IPC_FAILURE;
71 }
72
73 return XRT_SUCCESS;
74}
75
76xrt_result_t
77ipc_receive(struct ipc_message_channel *imc, void *out_data, size_t size)
78{
79
80 // wait for the response
81 struct iovec iov = {0};
82 struct msghdr msg = {0};
83
84 iov.iov_base = out_data;
85 iov.iov_len = size;
86
87 msg.msg_name = 0;
88 msg.msg_namelen = 0;
89 msg.msg_iov = &iov;
90 msg.msg_iovlen = 1;
91 msg.msg_flags = 0;
92
93 ssize_t len = recvmsg(imc->socket_fd, &msg, MSG_NOSIGNAL);
94
95 if (len < 0) {
96 int code = errno;
97 IPC_ERROR(imc, "ERROR: Receiving plain message on socket '%d' failed with error: '%i' '%s'!",
98 (int)imc->socket_fd, code, strerror(code));
99 return XRT_ERROR_IPC_FAILURE;
100 }
101
102 if ((size_t)len != size) {
103 IPC_ERROR(imc, "recvmsg failed with error: wrong size '%i', expected '%i'!", (int)len, (int)size);
104 return XRT_ERROR_IPC_FAILURE;
105 }
106
107 return XRT_SUCCESS;
108}
109
110union imcontrol_buf {
111 uint8_t buf[512];
112 struct cmsghdr align;
113};
114
115xrt_result_t
116ipc_receive_fds(struct ipc_message_channel *imc, void *out_data, size_t size, int *out_handles, uint32_t num_handles)
117{
118 assert(imc != NULL);
119 assert(out_data != NULL);
120 assert(size != 0);
121 assert(out_handles != NULL);
122 assert(num_handles != 0);
123 union imcontrol_buf u;
124 const size_t fds_size = sizeof(int) * num_handles;
125 const size_t cmsg_size = CMSG_SPACE(fds_size);
126 memset(u.buf, 0, cmsg_size);
127
128 struct iovec iov = {0};
129 iov.iov_base = out_data;
130 iov.iov_len = size;
131
132 struct msghdr msg = {0};
133 msg.msg_iov = &iov;
134 msg.msg_iovlen = 1;
135 msg.msg_control = u.buf;
136 msg.msg_controllen = cmsg_size;
137
138 ssize_t len = recvmsg(imc->socket_fd, &msg, MSG_NOSIGNAL);
139 if (len < 0) {
140 IPC_ERROR(imc, "recvmsg failed with error: '%s'!", strerror(errno));
141 return XRT_ERROR_IPC_FAILURE;
142 }
143
144 if (len == 0) {
145 IPC_ERROR(imc, "recvmsg failed with error: no data!");
146 return XRT_ERROR_IPC_FAILURE;
147 }
148 // Did the other side actually send file descriptors.
149 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
150 if (cmsg == NULL) {
151 return XRT_SUCCESS;
152 }
153
154 memcpy(out_handles, (int *)CMSG_DATA(cmsg), fds_size);
155 return XRT_SUCCESS;
156}
157
158xrt_result_t
159ipc_send_fds(struct ipc_message_channel *imc, const void *data, size_t size, const int *handles, uint32_t num_handles)
160{
161 assert(imc != NULL);
162 assert(data != NULL);
163 assert(size != 0);
164 assert(handles != NULL);
165
166 union imcontrol_buf u = {0};
167 size_t cmsg_size = CMSG_SPACE(sizeof(int) * num_handles);
168
169 struct iovec iov = {0};
170 iov.iov_base = (void *)data;
171 iov.iov_len = size;
172
173 struct msghdr msg = {0};
174 msg.msg_name = NULL;
175 msg.msg_namelen = 0;
176 msg.msg_iov = &iov;
177 msg.msg_iovlen = 1;
178 msg.msg_flags = 0;
179 msg.msg_control = u.buf;
180 msg.msg_controllen = cmsg_size;
181
182 const size_t fds_size = sizeof(int) * num_handles;
183 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
184 cmsg->cmsg_level = SOL_SOCKET;
185 cmsg->cmsg_type = SCM_RIGHTS;
186 cmsg->cmsg_len = CMSG_LEN(fds_size);
187
188 memcpy(CMSG_DATA(cmsg), handles, fds_size);
189
190 ssize_t ret = sendmsg(imc->socket_fd, &msg, MSG_NOSIGNAL);
191 if (ret < 0) {
192 IPC_ERROR(imc, "ERROR: sending %d FDs on socket %d failed with error: '%i' '%s'!", (int)num_handles,
193 imc->socket_fd, errno, strerror(errno));
194 for (uint32_t i = 0; i < num_handles; i++) {
195 IPC_ERROR(imc, "\tfd #%i: %i", i, handles[i]);
196 }
197 return XRT_ERROR_IPC_FAILURE;
198 }
199 return XRT_SUCCESS;
200}
201
202xrt_result_t
203ipc_receive_handles_shmem(
204 struct ipc_message_channel *imc, void *out_data, size_t size, xrt_shmem_handle_t *out_handles, uint32_t num_handles)
205{
206 return ipc_receive_fds(imc, out_data, size, out_handles, num_handles);
207}
208
209xrt_result_t
210ipc_send_handles_shmem(struct ipc_message_channel *imc,
211 const void *data,
212 size_t size,
213 const xrt_shmem_handle_t *handles,
214 uint32_t num_handles)
215{
216 return ipc_send_fds(imc, data, size, handles, num_handles);
217}
218
219
220/*
221 *
222 * AHardwareBuffer graphics buffer functions.
223 *
224 */
225
226#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
227
228#include <android/hardware_buffer.h>
229
230
231xrt_result_t
232ipc_receive_handles_graphics_buffer(struct ipc_message_channel *imc,
233 void *out_data,
234 size_t size,
235 xrt_graphics_buffer_handle_t *out_handles,
236 uint32_t num_handles)
237{
238 xrt_result_t result = ipc_receive(imc, out_data, size);
239 if (result != XRT_SUCCESS) {
240 return result;
241 }
242 bool failed = false;
243 for (uint32_t i = 0; i < num_handles; ++i) {
244 int err = AHardwareBuffer_recvHandleFromUnixSocket(imc->socket_fd, &(out_handles[i]));
245 if (err != 0) {
246 failed = true;
247 }
248 }
249 return failed ? XRT_ERROR_IPC_FAILURE : XRT_SUCCESS;
250}
251
252
253xrt_result_t
254ipc_send_handles_graphics_buffer(struct ipc_message_channel *imc,
255 const void *data,
256 size_t size,
257 const xrt_graphics_buffer_handle_t *handles,
258 uint32_t num_handles)
259{
260 xrt_result_t result = ipc_send(imc, data, size);
261 if (result != XRT_SUCCESS) {
262 return result;
263 }
264 bool failed = false;
265 for (uint32_t i = 0; i < num_handles; ++i) {
266 int err = AHardwareBuffer_sendHandleToUnixSocket(handles[i], imc->socket_fd);
267 if (err != 0) {
268 failed = true;
269 }
270 }
271 return failed ? XRT_ERROR_IPC_FAILURE : XRT_SUCCESS;
272}
273
274
275/*
276 *
277 * FD graphics buffer functions.
278 *
279 */
280
281#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
282
283xrt_result_t
284ipc_receive_handles_graphics_buffer(struct ipc_message_channel *imc,
285 void *out_data,
286 size_t size,
287 xrt_graphics_buffer_handle_t *out_handles,
288 uint32_t num_handles)
289{
290 return ipc_receive_fds(imc, out_data, size, out_handles, num_handles);
291}
292
293xrt_result_t
294ipc_send_handles_graphics_buffer(struct ipc_message_channel *imc,
295 const void *data,
296 size_t size,
297 const xrt_graphics_buffer_handle_t *handles,
298 uint32_t num_handles)
299{
300 return ipc_send_fds(imc, data, size, handles, num_handles);
301}
302
303#else
304#error "Need port to transport these graphics buffers"
305#endif
306
307
308/*
309 *
310 * FD graphics sync functions.
311 *
312 */
313
314#if defined(XRT_GRAPHICS_SYNC_HANDLE_IS_FD)
315
316xrt_result_t
317ipc_receive_handles_graphics_sync(struct ipc_message_channel *imc,
318 void *out_data,
319 size_t size,
320 xrt_graphics_sync_handle_t *out_handles,
321 uint32_t num_handles)
322{
323 //! @todo Temporary hack to send no handles.
324 if (num_handles == 0) {
325 return ipc_receive(imc, out_data, size);
326 } else {
327 return ipc_receive_fds(imc, out_data, size, out_handles, num_handles);
328 }
329}
330
331xrt_result_t
332ipc_send_handles_graphics_sync(struct ipc_message_channel *imc,
333 const void *data,
334 size_t size,
335 const xrt_graphics_sync_handle_t *handles,
336 uint32_t num_handles)
337{
338 //! @todo Temporary hack to send no handles.
339 if (num_handles == 0) {
340 return ipc_send(imc, data, size);
341 } else {
342 return ipc_send_fds(imc, data, size, handles, num_handles);
343 }
344}
345
346#else
347#error "Need port to transport these graphics buffers"
348#endif