VirtualBox

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

最後變更 在這個檔案從106790是 106790,由 vboxsync 提交於 5 月 前

Additions: Linux/Wayland: More renaming to belong to generic naming scheme, bugref:10796.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 15.9 KB
 
1/* $Id: wayland-helper-ipc.h 106790 2024-10-30 13:21:47Z 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.alldomusa.eu.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#ifndef VBOXWL_PATH
58# define VBOXWL_PATH "/usr/bin/vboxwl"
59#endif
60/** Limit maximum log verbosity level for popup tool. */
61#define VBOXWL_VERBOSITY_MAX (5)
62
63/** Arguments to vboxwl tool. */
64#define VBOXWL_ARG_CLIP_HG_COPY "--clip-hg-copy"
65#define VBOXWL_ARG_CLIP_GH_ANNOUNCE "--clip-gh-announce"
66#define VBOXWL_ARG_CLIP_GH_COPY "--clip-gh-copy"
67#define VBOXWL_ARG_SESSION_ID "--session-id"
68
69/** Time in milliseconds to wait for IPC socket events. */
70#define VBOX_GTKIPC_RX_TIMEOUT_MS (VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS)
71
72namespace vbcl
73{
74 namespace ipc
75 {
76 /** List of commands which VBoxClient and vboxwl use for IPC communication. */
77 typedef enum
78 {
79 /** Initializer. */
80 CMD_UNKNOWN = 0,
81 /** Send or receive list of clipboard formats which
82 * host or guest announces. */
83 VBOX_FORMATS,
84 /** Send or receive a clipboard format which host
85 * or guest requests. */
86 VBOX_FORMAT,
87 /** Send or receive clipboard data in given format. */
88 VBOX_DATA,
89 /** Termination of commands list. */
90 CMD_MAX
91 } command_t;
92
93 /** IPC command flow direction: from VBoxClient to vboxwl. */
94 const bool FLOW_DIRECTION_CLIENT = false;
95 /** IPC command flow direction: from vboxwl to VBoxClient. */
96 const bool FLOW_DIRECTION_SERVER = true;
97
98 /** IPC flow entry. */
99 typedef struct
100 {
101 /** Command ID. */
102 command_t enmCmd;
103 /** Flow direction. */
104 bool fDirection;
105 } flow_t;
106
107 /** IPC command header. */
108 typedef struct
109 {
110 /** IPC command packet checksum, includes header and payload. */
111 uint64_t u64Crc;
112 /** IPC session ID. Generated by VBoxClient instance and
113 * provided to vboxwl tool as a command line argument. Needs to be
114 * checked by both parties when data is received over IPC. */
115 uint32_t uSessionId;
116 /** IPC command identificator (opaque). */
117 command_t idCmd;
118 /** Size of payload data. */
119 uint64_t cbData;
120
121 } packet_t;
122
123 /**
124 * Log IPC packet content.
125 *
126 * @param pPacket Pointer to IPC packet data.
127 */
128 void packet_dump(vbcl::ipc::packet_t *pPacket);
129
130 /**
131 * Verify IPC packet integrity.
132 *
133 * @returns True if packet integrity check passed, False otherwise.
134 * @param pPacket Pointer to buffer which contains raw IPC packet data.
135 * @param cbPacket Size of buffer.
136 */
137 bool packet_verify(vbcl::ipc::packet_t *pPacket, size_t cbPacket);
138
139 /**
140 * Read entire packet from IPC socket.
141 *
142 * @returns IPRT status code. In case if success, output IPC packet
143 * is validated and its fields, such as packet size, can be trusted.
144 * @param uSessionId IPC session ID.
145 * @param hSession IPC session handle.
146 * @param ppvData Output buffer structured as validated
147 * IPC packet (contains size inside).
148 */
149 int packet_read(uint32_t uSessionId, RTLOCALIPCSESSION hSession, void **ppvData);
150
151 /**
152 * Write entire IPC packet into IPC socket.
153 *
154 * @returns IPRT status code.
155 * @param hSession IPC session handle.
156 * @param pPacket IPC packet.
157 */
158 int packet_write(RTLOCALIPCSESSION hSession, vbcl::ipc::packet_t *pPacket);
159
160 namespace data
161 {
162 /** Payload for IPC commands VBOX_FORMATS and VBOX_FORMAT. */
163 typedef struct
164 {
165 /** IPC command header. */
166 vbcl::ipc::packet_t Hdr;
167 /** Clipboard formats bitmask. */
168 SHCLFORMATS fFormats;
169 } formats_packet_t;
170
171 /** Payload for IPC command VBOX_DATA. */
172 typedef struct
173 {
174 /* IPC command header. */
175 vbcl::ipc::packet_t Hdr;
176 /** Clipboard buffer format. */
177 SHCLFORMAT uFmt;
178 /** Size of clipboard buffer data. */
179 uint64_t cbData;
180 } data_packet_t;
181
182 /**
183 * IPC commands flow is described as a table. Each entry of
184 * such table contains command ID and flow direction. Both
185 * sides, VBoxClient and vboxwl, go through exactly the same
186 * command flow table sequentially and depending on a role
187 * (client or server) either send or wait for data and receive
188 * it. When last table entry is reached by both sides
189 * (simultaneously) it means that IPC session is completed.
190 * If error occurs on either side in the middle of the flow,
191 * IPC session is aborted.
192 */
193
194 /** IPC flow description: Copy clipboard from host to guest. */
195 const flow_t HGCopyFlow[4] =
196 {
197 { VBOX_FORMATS, FLOW_DIRECTION_CLIENT },
198 { VBOX_FORMAT, FLOW_DIRECTION_SERVER },
199 { VBOX_DATA, FLOW_DIRECTION_CLIENT },
200 { CMD_MAX, false }
201 };
202
203 /** IPC flow description: Copy clipboard from guest to host. */
204 const flow_t GHCopyFlow[3] =
205 {
206 { VBOX_FORMAT, FLOW_DIRECTION_CLIENT },
207 { VBOX_DATA, FLOW_DIRECTION_SERVER },
208 { CMD_MAX, false }
209 };
210
211 /** IPC flow description: Announce guest's clipboard to the host
212 * and copy it to the host in format selected by host. */
213 const flow_t GHAnnounceAndCopyFlow[4] =
214 {
215 { VBOX_FORMATS, FLOW_DIRECTION_SERVER },
216 { VBOX_FORMAT, FLOW_DIRECTION_CLIENT },
217 { VBOX_DATA, FLOW_DIRECTION_SERVER },
218 { CMD_MAX, false }
219 };
220
221 class DataIpc
222 {
223 public:
224
225#ifdef RT_NEED_NEW_AND_DELETE
226 RTMEM_IMPLEMENT_NEW_AND_DELETE();
227#endif
228 DataIpc()
229 {}
230
231 /**
232 * Initialize memory.
233 *
234 * @param fServer Specify IPC role; if True, server role
235 * is assigned (set by VBoxClient),
236 * otherwise client role is assigned (vboxwl).
237 * @param uSessionId Unique IPC session ID (randomly generated
238 * by server).
239 */
240 void init(bool fServer, uint32_t uSessionId)
241 {
242 m_fFmts.init(VBOX_SHCL_FMT_NONE, VBCL_WAYLAND_VALUE_WAIT_TIMEOUT_MS);
243 m_uFmt.init(VBOX_SHCL_FMT_NONE, VBCL_WAYLAND_VALUE_WAIT_TIMEOUT_MS);
244 m_pvDataBuf.init(0, VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS);
245 m_cbDataBuf.init(0, VBCL_WAYLAND_DATA_WAIT_TIMEOUT_MS);
246 m_fServer = fServer;
247 m_uSessionId = uSessionId;
248 }
249
250 /**
251 * Reset IPC session data and free allocated resources.
252 */
253 void reset()
254 {
255 void *pvData = (void *)m_pvDataBuf.reset();
256 if (RT_VALID_PTR(pvData))
257 RTMemFree(pvData);
258
259 m_fFmts.reset();
260 m_uFmt.reset();
261 m_cbDataBuf.reset();
262 }
263
264 /**
265 * Process IPC flow from start to finish.
266 *
267 * @returns IPRT status code.
268 * @param pFlow Pointer to selected IPC flow.
269 * @param hIpcSession IPC connection handle.
270 */
271 int flow(const flow_t *pFlow, RTLOCALIPCSESSION hIpcSession)
272 {
273 int idx = 0;
274 int rc = VINF_SUCCESS;
275
276 while ( RT_SUCCESS(rc)
277 && pFlow[idx].enmCmd != CMD_MAX)
278 {
279 rc = select_fn(pFlow[idx].enmCmd, pFlow[idx].fDirection, hIpcSession);
280 idx++;
281 }
282
283 return rc;
284 }
285
286 /** IPC session internal data. */
287 Waitable<volatile SHCLFORMATS> m_fFmts;
288 Waitable<volatile SHCLFORMAT> m_uFmt;
289 Waitable<volatile uint64_t> m_pvDataBuf;
290 Waitable<volatile uint32_t> m_cbDataBuf;
291
292 protected:
293
294 /**
295 * Send available clipboard formats over IPC.
296 *
297 * @returns IPRT status code.
298 * @param uSessionId IPC session ID.
299 * @param hIpcSession IPC connection handle.
300 */
301 int send_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
302
303 /**
304 * Receive available clipboard formats over IPC.
305 *
306 * @returns IPRT status code.
307 * @param uSessionId IPC session ID.
308 * @param hIpcSession IPC connection handle.
309 */
310 int recv_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
311
312 /**
313 * Send requested clipboard format over IPC.
314 *
315 * @returns IPRT status code.
316 * @param uSessionId IPC session ID.
317 * @param hIpcSession IPC connection handle.
318 */
319 int send_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
320
321 /**
322 * Receive requested clipboard format over IPC.
323 *
324 * @returns IPRT status code.
325 * @param uSessionId IPC session ID.
326 * @param hIpcSession IPC connection handle.
327 */
328 int recv_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
329
330 /**
331 * Send clipboard buffer over IPC.
332 *
333 * @returns IPRT status code.
334 * @param uSessionId IPC session ID.
335 * @param hIpcSession IPC connection handle.
336 */
337 int send_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
338
339 /**
340 * Receive clipboard buffer over IPC.
341 *
342 * @returns IPRT status code.
343 * @param uSessionId IPC session ID.
344 * @param hIpcSession IPC connection handle.
345 */
346 int recv_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession);
347
348 /**
349 * Take one step flow action.
350 *
351 * Taking into account given command and IPC role, either
352 * send or receive data from IPC socket.
353 *
354 * @returns IPRT status code.
355 * @param enmCmd IPC command ID.
356 * @param fDirection IPC role.
357 * @param hIpcSession IPC connection handle.
358 */
359 int select_fn(command_t enmCmd, bool fDirection, RTLOCALIPCSESSION hIpcSession)
360 {
361 int rc = VERR_INVALID_PARAMETER;
362 bool fShouldSend;
363
364 if (m_fServer)
365 fShouldSend = (fDirection == FLOW_DIRECTION_CLIENT);
366 else
367 fShouldSend = (fDirection == FLOW_DIRECTION_SERVER);
368
369 switch(enmCmd)
370 {
371 case VBOX_FORMATS:
372 {
373 if (fShouldSend)
374 rc = send_formats(m_uSessionId, hIpcSession);
375 else
376 rc = recv_formats(m_uSessionId, hIpcSession);
377 break;
378 }
379
380 case VBOX_FORMAT:
381 {
382 if (fShouldSend)
383 rc = send_format(m_uSessionId, hIpcSession);
384 else
385 rc = recv_format(m_uSessionId, hIpcSession);
386 break;
387 }
388
389 case VBOX_DATA:
390 {
391 if (fShouldSend)
392 rc = send_data(m_uSessionId, hIpcSession);
393 else
394 rc = recv_data(m_uSessionId, hIpcSession);
395 break;
396 }
397
398 default:
399 break;
400 }
401
402 return rc;
403 }
404
405 bool m_fServer;
406 uint32_t m_uSessionId;
407 };
408 }
409 }
410}
411
412/**
413 * Helper function to get Gtk helper IPC server name.
414 *
415 * This function should be used by both IPC server and client code
416 * in order to connect one to another. Output string will be in
417 * format: GtkHlpIpcServer-&lt;active tty&gt;-&lt;user name&gt;.
418 *
419 * @returns IPRT status code.
420 * @param szBuf Where to store generated name string.
421 * @param cbBuf Size of buffer.
422 */
423RTDECL(int) vbcl_wayland_hlp_gtk_ipc_srv_name(char *szBuf, size_t cbBuf);
424
425#endif /* !GA_INCLUDED_SRC_x11_VBoxClient_wayland_helper_ipc_h */
426
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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