VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/wayland-helper-ipc.h@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.9 KB
Line 
1/* $Id: wayland-helper-ipc.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Guest Additions - Definitions for IPC between VBoxClient and vboxwl tool.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef GA_INCLUDED_SRC_x11_VBoxClient_wayland_helper_ipc_h
29#define GA_INCLUDED_SRC_x11_VBoxClient_wayland_helper_ipc_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <sys/types.h>
35#include <pwd.h>
36#include <unistd.h>
37
38#include <iprt/cdefs.h>
39#include <iprt/err.h>
40#include <iprt/linux/sysfs.h>
41#include <iprt/localipc.h>
42#include <iprt/mem.h>
43#include <iprt/crc.h>
44#include <iprt/env.h>
45#include <iprt/process.h>
46#include <iprt/asm.h>
47#include <iprt/time.h>
48#include <iprt/nocrt/new>
49
50#include <VBox/GuestHost/clipboard-helper.h>
51
52#include "VBoxClient.h"
53#include "wayland-helper.h"
54
55/** Path to Gtk helper tool which raises popup window and gets
56 * access to Wayland clipboard. */
57#define VBOXWL_PATH "/usr/bin/vboxwl"
58/** Limit maximum log verbosity level for popup tool. */
59#define VBOXWL_VERBOSITY_MAX (5)
60
61/** Arguments to vboxwl tool. */
62#define VBOXWL_ARG_CLIP_HG_COPY "--clip-hg-copy"
63#define VBOXWL_ARG_CLIP_GH_ANNOUNCE "--clip-gh-announce"
64#define VBOXWL_ARG_CLIP_GH_COPY "--clip-gh-copy"
65#define VBOXWL_ARG_SESSION_ID "--session-id"
66
67/** Time in milliseconds to wait for IPC socket events. */
68#define VBOX_GTKIPC_RX_TIMEOUT_MS (VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS)
69
70namespace vbcl
71{
72 namespace ipc
73 {
74 /** List of commands which VBoxClient and vboxwl use for IPC communication. */
75 typedef enum
76 {
77 /** Initializer. */
78 CMD_UNKNOWN = 0,
79 /** Send or receive list of clipboard formats which
80 * host or guest announces. */
81 CLIP_FORMATS,
82 /** Send or receive a clipboard format which host
83 * or guest requests. */
84 CLIP_FORMAT,
85 /** Send or receive clipboard data in given format. */
86 CLIP_DATA,
87 /** Termination of commands list. */
88 CMD_MAX
89 } command_t;
90
91 /** IPC command flow direction: from VBoxClient to vboxwl. */
92 const bool FLOW_DIRECTION_CLIENT = false;
93 /** IPC command flow direction: from vboxwl to VBoxClient. */
94 const bool FLOW_DIRECTION_SERVER = true;
95
96 /** IPC flow entry. */
97 typedef struct
98 {
99 /** Command ID. */
100 command_t enmCmd;
101 /** Flow direction. */
102 bool fDirection;
103 } flow_t;
104
105 /** IPC command header. */
106 typedef struct
107 {
108 /** IPC command packet checksum, includes header and payload. */
109 uint64_t u64Crc;
110 /** IPC session ID. Generated by VBoxClient instance and
111 * provided to vboxwl tool as a command line argument. Needs to be
112 * checked by both parties when data is received over IPC. */
113 uint32_t uSessionId;
114 /** IPC command identificator (opaque). */
115 command_t idCmd;
116 /** Size of payload data. */
117 uint64_t cbData;
118
119 } packet_t;
120
121 /**
122 * Log IPC packet content.
123 *
124 * @param pPacket Pointer to IPC packet data.
125 */
126 void packet_dump(vbcl::ipc::packet_t *pPacket);
127
128 /**
129 * Verify IPC packet integrity.
130 *
131 * @returns True if packet integrity check passed, False otherwise.
132 * @param pPacket Pointer to buffer which contains raw IPC packet data.
133 * @param cbPacket Size of buffer.
134 */
135 bool packet_verify(vbcl::ipc::packet_t *pPacket, size_t cbPacket);
136
137 /**
138 * Read entire packet from IPC socket.
139 *
140 * @returns IPRT status code. In case if success, output IPC packet
141 * is validated and its fields, such as packet size, can be trusted.
142 * @param uSessionId IPC session ID.
143 * @param hSession IPC session handle.
144 * @param ppvData Output buffer structured as validated
145 * IPC packet (contains size inside).
146 */
147 int packet_read(uint32_t uSessionId, RTLOCALIPCSESSION hSession, void **ppvData);
148
149 /**
150 * Write entire IPC packet into IPC socket.
151 *
152 * @returns IPRT status code.
153 * @param hSession IPC session handle.
154 * @param pPacket IPC packet.
155 */
156 int packet_write(RTLOCALIPCSESSION hSession, vbcl::ipc::packet_t *pPacket);
157
158 namespace clipboard
159 {
160 /** Payload for IPC commands CLIP_FORMATS and CLIP_FORMAT. */
161 typedef struct
162 {
163 /** IPC command header. */
164 vbcl::ipc::packet_t Hdr;
165 /** Clipboard formats bitmask. */
166 SHCLFORMATS fFormats;
167 } formats_packet_t;
168
169 /** Payload for IPC command CLIP_DATA. */
170 typedef struct
171 {
172 /* IPC command header. */
173 vbcl::ipc::packet_t Hdr;
174 /** Clipboard buffer format. */
175 SHCLFORMAT uFmt;
176 /** Size of clipboard buffer data. */
177 uint64_t cbData;
178 } data_packet_t;
179
180 /**
181 * IPC commands flow is described as a table. Each entry of
182 * such table contains command ID and flow direction. Both
183 * sides, VBoxClient and vboxwl, go through exactly the same
184 * command flow table sequentially and depending on a role
185 * (client or server) either send or wait for data and receive
186 * it. When last table entry is reached by both sides
187 * (simultaneously) it means that IPC session is completed.
188 * If error occurs on either side in the middle of the flow,
189 * IPC session is aborted.
190 */
191
192 /** IPC flow description: Copy clipboard from host to guest. */
193 const flow_t HGCopyFlow[4] =
194 {
195 { CLIP_FORMATS, FLOW_DIRECTION_CLIENT },
196 { CLIP_FORMAT, FLOW_DIRECTION_SERVER },
197 { CLIP_DATA, FLOW_DIRECTION_CLIENT },
198 { CMD_MAX, false }
199 };
200
201 /** IPC flow description: Copy clipboard from guest to host. */
202 const flow_t GHCopyFlow[3] =
203 {
204 { CLIP_FORMAT, FLOW_DIRECTION_CLIENT },
205 { CLIP_DATA, FLOW_DIRECTION_SERVER },
206 { CMD_MAX, false }
207 };
208
209 /** IPC flow description: Announce guest's clipboard to the host
210 * and copy it to the host in format selected by host. */
211 const flow_t GHAnnounceAndCopyFlow[4] =
212 {
213 { CLIP_FORMATS, FLOW_DIRECTION_SERVER },
214 { CLIP_FORMAT, FLOW_DIRECTION_CLIENT },
215 { CLIP_DATA, FLOW_DIRECTION_SERVER },
216 { CMD_MAX, false }
217 };
218
219 class ClipboardIpc
220 {
221 public:
222
223#ifdef RT_NEED_NEW_AND_DELETE
224 RTMEM_IMPLEMENT_NEW_AND_DELETE();
225#endif
226 ClipboardIpc()
227 {}
228
229 /**
230 * Initialize memory.
231 *
232 * @param fServer Specify IPC role; if True, server role
233 * is assigned (set by VBoxClient),
234 * otherwise client role is assigned (vboxwl).
235 * @param uSessionId Unique IPC session ID (randomly generated
236 * by server).
237 */
238 void init(bool fServer, uint32_t uSessionId)
239 {
240 m_fFmts.init(VBOX_SHCL_FMT_NONE, VBCL_WAYLAND_VALUE_WAIT_TIMEOUT_MS);
241 m_uFmt.init(VBOX_SHCL_FMT_NONE, VBCL_WAYLAND_VALUE_WAIT_TIMEOUT_MS);
242 m_pvClipboardBuf.init(0, VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS);
243 m_cbClipboardBuf.init(0, VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS);
244 m_fServer = fServer;
245 m_uSessionId = uSessionId;
246 }
247
248 /**
249 * Reset IPC session data and free allocated resources.
250 */
251 void reset()
252 {
253 void *pvData = (void *)m_pvClipboardBuf.reset();
254 if (RT_VALID_PTR(pvData))
255 RTMemFree(pvData);
256
257 m_fFmts.reset();
258 m_uFmt.reset();
259 m_cbClipboardBuf.reset();
260 }
261
262 /**
263 * Process IPC flow from start to finish.
264 *
265 * @returns IPRT status code.
266 * @param pFlow Pointer to selected IPC flow.
267 * @param hIpcSession IPC connection handle.
268 */
269 int flow(const flow_t *pFlow, RTLOCALIPCSESSION hIpcSession)
270 {
271 int idx = 0;
272 int rc = VINF_SUCCESS;
273
274 while ( RT_SUCCESS(rc)
275 && pFlow[idx].enmCmd != CMD_MAX)
276 {
277 rc = select_fn(pFlow[idx].enmCmd, pFlow[idx].fDirection, hIpcSession);
278 idx++;
279 }
280
281 return rc;
282 }
283
284 /** IPC session internal data. */
285 Waitable<volatile SHCLFORMATS> m_fFmts;
286 Waitable<volatile SHCLFORMAT> m_uFmt;
287 Waitable<volatile uint64_t> m_pvClipboardBuf;
288 Waitable<volatile uint32_t> m_cbClipboardBuf;
289
290 protected:
291
292 /**
293 * Send available clipboard formats over IPC.
294 *
295 * @returns IPRT status code.
296 * @param uSessionId IPC session ID.
297 * @param hIpcSession IPC connection handle.
298 */
299 int send_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
300
301 /**
302 * Receive available clipboard formats over IPC.
303 *
304 * @returns IPRT status code.
305 * @param uSessionId IPC session ID.
306 * @param hIpcSession IPC connection handle.
307 */
308 int recv_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
309
310 /**
311 * Send requested clipboard format over IPC.
312 *
313 * @returns IPRT status code.
314 * @param uSessionId IPC session ID.
315 * @param hIpcSession IPC connection handle.
316 */
317 int send_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
318
319 /**
320 * Receive requested clipboard format over IPC.
321 *
322 * @returns IPRT status code.
323 * @param uSessionId IPC session ID.
324 * @param hIpcSession IPC connection handle.
325 */
326 int recv_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
327
328 /**
329 * Send clipboard buffer over IPC.
330 *
331 * @returns IPRT status code.
332 * @param uSessionId IPC session ID.
333 * @param hIpcSession IPC connection handle.
334 */
335 int send_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
336
337 /**
338 * Receive clipboard buffer over IPC.
339 *
340 * @returns IPRT status code.
341 * @param uSessionId IPC session ID.
342 * @param hIpcSession IPC connection handle.
343 */
344 int recv_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
345
346 /**
347 * Take one step flow action.
348 *
349 * Taking into account given command and IPC role, either
350 * send or receive data from IPC socket.
351 *
352 * @returns IPRT status code.
353 * @param enmCmd IPC command ID.
354 * @param fDirection IPC role.
355 * @param hIpcSession IPC connection handle.
356 */
357 int select_fn(command_t enmCmd, bool fDirection, RTLOCALIPCSESSION hIpcSession)
358 {
359 int rc = VERR_INVALID_PARAMETER;
360 bool fShouldSend;
361
362 if (m_fServer)
363 fShouldSend = (fDirection == FLOW_DIRECTION_CLIENT);
364 else
365 fShouldSend = (fDirection == FLOW_DIRECTION_SERVER);
366
367 switch(enmCmd)
368 {
369 case CLIP_FORMATS:
370 {
371 if (fShouldSend)
372 rc = send_formats(m_uSessionId, hIpcSession);
373 else
374 rc = recv_formats(m_uSessionId, hIpcSession);
375 break;
376 }
377
378 case CLIP_FORMAT:
379 {
380 if (fShouldSend)
381 rc = send_format(m_uSessionId, hIpcSession);
382 else
383 rc = recv_format(m_uSessionId, hIpcSession);
384 break;
385 }
386
387 case CLIP_DATA:
388 {
389 if (fShouldSend)
390 rc = send_data(m_uSessionId, hIpcSession);
391 else
392 rc = recv_data(m_uSessionId, hIpcSession);
393 break;
394 }
395
396 default:
397 break;
398 }
399
400 return rc;
401 }
402
403 bool m_fServer;
404 uint32_t m_uSessionId;
405 };
406 }
407 }
408}
409
410/**
411 * Helper function to get Gtk helper IPC server name.
412 *
413 * This function should be used by both IPC server and client code
414 * in order to connect one to another. Output string will be in
415 * format: GtkHlpIpcServer-&lt;active tty&gt;-&lt;user name&gt;.
416 *
417 * @returns IPRT status code.
418 * @param szBuf Where to store generated name string.
419 * @param cbBuf Size of buffer.
420 */
421RTDECL(int) vbcl_wayland_hlp_gtk_ipc_srv_name(char *szBuf, size_t cbBuf);
422
423#endif /* !GA_INCLUDED_SRC_x11_VBoxClient_wayland_helper_ipc_h */
424
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette