VirtualBox

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

Last change on this file since 101881 was 101881, checked in by vboxsync, 6 months ago

Additions: X11/Wayland: fix building issues with older gcc (4.1.2), bugref:10194.

  • 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 101881 2023-11-06 16:29:36Z vboxsync $ */
2/** @file
3 * Guest Additions - Definitions for IPC between VBoxClient and vboxwl tool.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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 uSessionId 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 uSessionId 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 uSessionId IPC connection handle.
316 */
317 int send_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
318
319
320 /**
321 * Receive requested clipboard format over IPC.
322 *
323 * @returns IPRT status code.
324 * @param uSessionId IPC session ID.
325 * @param uSessionId IPC connection handle.
326 */
327 int recv_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
328
329 /**
330 * Send clipboard buffer over IPC.
331 *
332 * @returns IPRT status code.
333 * @param uSessionId IPC session ID.
334 * @param uSessionId IPC connection handle.
335 */
336 int send_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
337
338 /**
339 * Receive clipboard buffer over IPC.
340 *
341 * @returns IPRT status code.
342 * @param uSessionId IPC session ID.
343 * @param uSessionId IPC connection handle.
344 */
345 int recv_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
346
347 /**
348 * Take one step flow action.
349 *
350 * Taking into account given command and IPC role, either
351 * send or receive data from IPC socket.
352 *
353 * @returns IPRT status code.
354 * @param enmCmd IPC command ID.
355 * @param fDirection IPC role.
356 * @param hIpcSession IPC connection handle.
357 */
358 int select_fn(command_t enmCmd, bool fDirection, RTLOCALIPCSESSION hIpcSession)
359 {
360 int rc = VERR_INVALID_PARAMETER;
361 bool fShouldSend;
362
363 if (m_fServer)
364 fShouldSend = (fDirection == FLOW_DIRECTION_CLIENT);
365 else
366 fShouldSend = (fDirection == FLOW_DIRECTION_SERVER);
367
368 switch(enmCmd)
369 {
370 case CLIP_FORMATS:
371 {
372 if (fShouldSend)
373 rc = send_formats(m_uSessionId, hIpcSession);
374 else
375 rc = recv_formats(m_uSessionId, hIpcSession);
376 break;
377 }
378
379 case CLIP_FORMAT:
380 {
381 if (fShouldSend)
382 rc = send_format(m_uSessionId, hIpcSession);
383 else
384 rc = recv_format(m_uSessionId, hIpcSession);
385 break;
386 }
387
388 case CLIP_DATA:
389 {
390 if (fShouldSend)
391 rc = send_data(m_uSessionId, hIpcSession);
392 else
393 rc = recv_data(m_uSessionId, hIpcSession);
394 break;
395 }
396
397 default:
398 break;
399 }
400
401 return rc;
402 }
403
404 bool m_fServer;
405 uint32_t m_uSessionId;
406 };
407 }
408 }
409}
410
411/**
412 * Helper function to get Gtk helper IPC server name.
413 *
414 * This function should be used by both IPC server and client code
415 * in order to connect one to another. Output string will be in
416 * format: GtkHlpIpcServer-<active tty>-<user name>.
417 *
418 * @returns IPRT status code.
419 * @param szBuf Where to store generated name string.
420 * @param cbBuf Size of buffer.
421 */
422RTDECL(int) vbcl_wayland_hlp_gtk_ipc_srv_name(char *szBuf, size_t cbBuf);
423
424#endif /* !GA_INCLUDED_SRC_x11_VBoxClient_wayland_helper_ipc_h */
425
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use