VirtualBox

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

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

Copyright year updates by scm.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 13.0 KB
 
1/* $Id: wayland-helper-ipc.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Guest Additions - 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#include <sys/types.h>
29#include <pwd.h>
30#include <unistd.h>
31
32#include <iprt/cdefs.h>
33#include <iprt/err.h>
34#include <iprt/linux/sysfs.h>
35#include <iprt/localipc.h>
36#include <iprt/mem.h>
37#include <iprt/crc.h>
38#include <iprt/env.h>
39#include <iprt/process.h>
40#include <iprt/asm.h>
41
42#include <VBox/GuestHost/clipboard-helper.h>
43
44#include "VBoxClient.h"
45#include "wayland-helper-ipc.h"
46
47RTDECL(int) vbcl_wayland_hlp_gtk_ipc_srv_name(char *szBuf, size_t cbBuf)
48{
49 int rc;
50
51 char pszActiveTTY[128];
52 size_t cchRead;
53 struct passwd *pwd;
54
55 AssertReturn(RT_VALID_PTR(szBuf), VERR_INVALID_PARAMETER);
56 AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER);
57
58 RT_BZERO(szBuf, cbBuf);
59 RT_ZERO(pszActiveTTY);
60
61 rc = RTStrCat(szBuf, cbBuf, "GtkHlpIpcServer-");
62 if (RT_SUCCESS(rc))
63 rc = RTLinuxSysFsReadStrFile(pszActiveTTY, sizeof(pszActiveTTY) - 1 /* reserve last byte for string termination */,
64 &cchRead, "class/tty/tty0/active");
65 if (RT_SUCCESS(rc))
66 rc = RTStrCat(szBuf, cbBuf, pszActiveTTY);
67
68 if (RT_SUCCESS(rc))
69 rc = RTStrCat(szBuf, cbBuf, "-");
70
71 pwd = getpwuid(geteuid());
72 if (RT_VALID_PTR(pwd))
73 {
74 if (RT_VALID_PTR(pwd->pw_name))
75 rc = RTStrCat(szBuf, cbBuf, pwd->pw_name);
76 else
77 rc = VERR_NOT_FOUND;
78 }
79 else
80 rc = VERR_NOT_FOUND;
81
82 return rc;
83}
84
85void vbcl::ipc::packet_dump(vbcl::ipc::packet_t *pPacket)
86{
87 VBClLogVerbose(3, "IPC packet dump:\n");
88 VBClLogVerbose(3, "u64Crc : 0x%x\n", pPacket->u64Crc);
89 VBClLogVerbose(3, "uSessionId: %u\n", pPacket->uSessionId);
90 VBClLogVerbose(3, "idCmd : %u\n", pPacket->idCmd);
91 VBClLogVerbose(3, "cbData: : %u\n", pPacket->cbData);
92}
93
94bool vbcl::ipc::packet_verify(vbcl::ipc::packet_t *pPacket, size_t cbPacket)
95{
96 bool fResult = false;
97
98 AssertPtrReturn(pPacket, VERR_INVALID_PARAMETER);
99 AssertReturn(cbPacket > sizeof(vbcl::ipc::packet_t), VERR_INVALID_PARAMETER);
100
101 AssertReturn( pPacket->idCmd > vbcl::ipc::CMD_UNKNOWN
102 && pPacket->idCmd < vbcl::ipc::CMD_MAX, VERR_INVALID_PARAMETER);
103
104 /* Exact size match. */
105 if (pPacket->cbData == cbPacket)
106 {
107 /* CRC check. */
108 uint64_t u64Crc = pPacket->u64Crc;
109 pPacket->u64Crc = 0;
110 if (u64Crc != 0 && RTCrc64(pPacket, pPacket->cbData) == u64Crc)
111 {
112 /* Verify payload size. */
113 size_t cbPayload = 0;
114
115 switch (pPacket->idCmd)
116 {
117 case vbcl::ipc::CLIP_FORMATS:
118 case vbcl::ipc::CLIP_FORMAT:
119 cbPayload = sizeof(vbcl::ipc::clipboard::formats_packet_t);
120 break;
121
122 case vbcl::ipc::CLIP_DATA:
123 {
124 vbcl::ipc::clipboard::data_packet_t *pDataEx = (vbcl::ipc::clipboard::data_packet_t *)pPacket;
125 cbPayload = sizeof(vbcl::ipc::clipboard::data_packet_t) + pDataEx->cbData;
126 break;
127 }
128
129 default:
130 break;
131 }
132
133 if (pPacket->cbData == cbPayload)
134 fResult = true;
135 else
136 VBClLogVerbose(3, "bad cmd size (%u vs %u)\n", pPacket->cbData, cbPayload);
137 }
138 else
139 VBClLogVerbose(3, "bad crc\n");
140
141 /* Restore CRC. */
142 pPacket->u64Crc = u64Crc;
143 }
144 else
145 VBClLogVerbose(3, "bad size\n");
146
147 return fResult;
148}
149
150int vbcl::ipc::packet_read(uint32_t uSessionId, RTLOCALIPCSESSION hSession, void **ppvData)
151{
152 int rc;
153
154 vbcl::ipc::packet_t Packet;
155
156 AssertPtrReturn(ppvData, VERR_INVALID_PARAMETER);
157
158 rc = RTLocalIpcSessionWaitForData(hSession, VBOX_GTKIPC_RX_TIMEOUT_MS);
159 if (RT_SUCCESS(rc))
160 {
161 /* Read IPC message header. */
162 rc = RTLocalIpcSessionRead(hSession, &Packet, sizeof(Packet), NULL);
163 if (RT_SUCCESS(rc))
164 {
165 bool fCheck = true;
166
167#define _CHECK(_cond, _msg, _ptr) \
168 if (fCheck) \
169 { \
170 fCheck &= _cond; \
171 if (!fCheck) \
172 VBClLogVerbose(3, _msg "\n", _ptr); \
173 }
174
175 _CHECK(Packet.u64Crc > 0, "bad crc: 0x%x", Packet.u64Crc);
176 _CHECK(Packet.uSessionId == uSessionId, "bad session id: %u vs %u", (Packet.uSessionId, uSessionId));
177 _CHECK(Packet.cbData > sizeof(Packet), "bad cbData: %u", Packet.cbData);
178
179 /* Receive the rest of a message. */
180 if (fCheck)
181 {
182 uint8_t *puData;
183
184 puData = (uint8_t *)RTMemAllocZ(Packet.cbData);
185 if (RT_VALID_PTR(puData))
186 {
187 /* Add generic header to the beginning of the output buffer
188 * and receive the rest of the data into it. */
189 memcpy(puData, &Packet, sizeof(Packet));
190
191 rc = RTLocalIpcSessionRead(hSession, puData + sizeof(Packet),
192 Packet.cbData - sizeof(Packet), NULL);
193 if (RT_SUCCESS(rc))
194 {
195 if (vbcl::ipc::packet_verify((vbcl::ipc::packet_t *)puData, Packet.cbData))
196 {
197 /* Now return received data to the caller. */
198 *ppvData = puData;
199 }
200 else
201 rc = VERR_NOT_EQUAL;
202 }
203
204 if (RT_FAILURE(rc))
205 RTMemFree(puData);
206 }
207 else
208 rc = VERR_NO_MEMORY;
209 }
210 else
211 rc = VERR_INVALID_PARAMETER;
212
213 if (RT_FAILURE(rc))
214 vbcl::ipc::packet_dump(&Packet);
215 }
216 }
217
218 return rc;
219}
220
221int vbcl::ipc::packet_write(RTLOCALIPCSESSION hSession, vbcl::ipc::packet_t *pPacket)
222{
223 int rc;
224
225 AssertPtrReturn(pPacket, VERR_INVALID_PARAMETER);
226
227 pPacket->u64Crc = 0;
228 pPacket->u64Crc = RTCrc64(pPacket, pPacket->cbData);
229
230 Assert(pPacket->u64Crc);
231
232 if (vbcl::ipc::packet_verify(pPacket, pPacket->cbData))
233 {
234 rc = RTLocalIpcSessionWrite(hSession, (void *)pPacket, pPacket->cbData);
235 if (RT_SUCCESS(rc))
236 rc = RTLocalIpcSessionFlush(hSession);
237 }
238 else
239 {
240 vbcl::ipc::packet_dump(pPacket);
241 rc = VERR_NOT_EQUAL;
242 }
243
244 return rc;
245}
246
247int vbcl::ipc::clipboard::ClipboardIpc::send_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
248{
249 vbcl::ipc::clipboard::formats_packet_t Packet;
250 SHCLFORMATS fFormats;
251 int rc = VINF_SUCCESS;
252
253 RT_ZERO(Packet);
254
255 Packet.Hdr.u64Crc = 0;
256 Packet.Hdr.uSessionId = uSessionId;
257 Packet.Hdr.idCmd = CLIP_FORMATS;
258 Packet.Hdr.cbData = sizeof(Packet);
259
260 fFormats = m_fFmts.wait();
261 if (fFormats != m_fFmts.defaults())
262 {
263 Packet.fFormats = fFormats;
264 rc = vbcl::ipc::packet_write(hIpcSession, &Packet.Hdr);
265 }
266 else
267 rc = VERR_TIMEOUT;
268
269 VBClLogVerbose(3, "%s: send_formats [sid=%u, fmts=0x%x], rc=%Rrc\n",
270 m_fServer ? "server" : "client", uSessionId, fFormats, rc);
271
272 return rc;
273}
274
275int vbcl::ipc::clipboard::ClipboardIpc::recv_formats(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
276{
277 int rc;
278 vbcl::ipc::clipboard::formats_packet_t *pPacket;
279 vbcl::ipc::command_t idCmd = CMD_UNKNOWN;
280 SHCLFORMATS fFormats = VBOX_SHCL_FMT_NONE;
281
282 rc = vbcl::ipc::packet_read(uSessionId, hIpcSession, (void **)&pPacket);
283 if (RT_SUCCESS(rc))
284 {
285 if ( pPacket->Hdr.idCmd == CLIP_FORMATS
286 && vbcl::ipc::packet_verify(&pPacket->Hdr, pPacket->Hdr.cbData))
287 {
288 fFormats = pPacket->fFormats;
289 idCmd = pPacket->Hdr.idCmd;
290 m_fFmts.set(fFormats);
291 }
292 else
293 rc = VERR_WRONG_ORDER;
294
295 RTMemFree(pPacket);
296 }
297
298 VBClLogVerbose(3, "%s: recv_formats [sid=%u, cmd=0x%x, fmts=0x%x], rc=%Rrc\n",
299 m_fServer ? "server" : "client", uSessionId, idCmd, fFormats, rc);
300
301 return rc;
302}
303
304int vbcl::ipc::clipboard::ClipboardIpc::send_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
305{
306 vbcl::ipc::clipboard::formats_packet_t Packet;
307 SHCLFORMAT uFormat;
308 int rc = VINF_SUCCESS;
309
310 RT_ZERO(Packet);
311
312 Packet.Hdr.u64Crc = 0;
313 Packet.Hdr.uSessionId = uSessionId;
314 Packet.Hdr.idCmd = CLIP_FORMAT;
315 Packet.Hdr.cbData = sizeof(Packet);
316
317 uFormat = m_uFmt.wait();
318 if (uFormat != m_uFmt.defaults())
319 {
320 Packet.fFormats = uFormat;
321 rc = vbcl::ipc::packet_write(hIpcSession, &Packet.Hdr);
322 }
323 else
324 rc = VERR_TIMEOUT;
325
326 VBClLogVerbose(3, "%s: send_format [sid=%u, fmt=0x%x], rc=%Rrc\n",
327 m_fServer ? "server" : "client", uSessionId, uFormat, rc);
328
329 return rc;
330}
331
332int vbcl::ipc::clipboard::ClipboardIpc::recv_format(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
333{
334 int rc;
335 vbcl::ipc::clipboard::formats_packet_t *pPacket;
336 vbcl::ipc::command_t idCmd = CMD_UNKNOWN;
337 SHCLFORMATS uFormat = VBOX_SHCL_FMT_NONE;
338
339 rc = vbcl::ipc::packet_read(uSessionId, hIpcSession, (void **)&pPacket);
340 if (RT_SUCCESS(rc))
341 {
342 if ( pPacket->Hdr.idCmd == CLIP_FORMAT
343 && vbcl::ipc::packet_verify(&pPacket->Hdr, pPacket->Hdr.cbData))
344 {
345 uFormat = pPacket->fFormats;
346 idCmd = pPacket->Hdr.idCmd;
347 m_uFmt.set(uFormat);
348 }
349 else
350 rc = VERR_WRONG_ORDER;
351
352 RTMemFree(pPacket);
353 }
354
355 VBClLogVerbose(3, "%s: recv_format [sid=%u, cmd=0x%x, fmts=0x%x], rc=%Rrc\n",
356 m_fServer ? "server" : "client", uSessionId, idCmd, uFormat, rc);
357
358 return rc;
359}
360
361int vbcl::ipc::clipboard::ClipboardIpc::send_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
362{
363 vbcl::ipc::clipboard::data_packet_t *pPacket;
364 int rc = VINF_SUCCESS;
365
366 void *pvData;
367 uint32_t cbData;
368
369 cbData = m_cbClipboardBuf.wait();
370 pvData = (void *)m_pvClipboardBuf.wait();
371 if ( cbData != m_cbClipboardBuf.defaults()
372 && pvData != (void *)m_pvClipboardBuf.defaults())
373 {
374 pPacket = (vbcl::ipc::clipboard::data_packet_t *)RTMemAllocZ(sizeof(vbcl::ipc::clipboard::data_packet_t) + cbData);
375 if (RT_VALID_PTR(pPacket))
376 {
377 pPacket->Hdr.u64Crc = 0;
378 pPacket->Hdr.uSessionId = uSessionId;
379 pPacket->Hdr.idCmd = CLIP_DATA;
380 pPacket->Hdr.cbData = sizeof(vbcl::ipc::clipboard::data_packet_t) + cbData;
381 pPacket->cbData = cbData;
382
383 memcpy((uint8_t *)pPacket + sizeof(vbcl::ipc::clipboard::data_packet_t), pvData, cbData);
384 rc = vbcl::ipc::packet_write(hIpcSession, &pPacket->Hdr);
385 RTMemFree(pPacket);
386 }
387 else
388 rc = VERR_NO_MEMORY;
389 }
390 else
391 rc = VERR_TIMEOUT;
392
393 VBClLogVerbose(3, "%s: send_data [sid=%u, cbData=%u], rc=%Rrc\n",
394 m_fServer ? "server" : "client", uSessionId, cbData, rc);
395
396 return rc;
397}
398
399int vbcl::ipc::clipboard::ClipboardIpc::recv_data(uint32_t uSessionId, RTLOCALIPCSESSION hIpcSession)
400{
401 int rc;
402 vbcl::ipc::clipboard::data_packet_t *pPacket;
403 vbcl::ipc::command_t idCmd = CMD_UNKNOWN;
404 uint32_t cbData = 0;
405
406 rc = vbcl::ipc::packet_read(uSessionId, hIpcSession, (void **)&pPacket);
407 if (RT_SUCCESS(rc))
408 {
409 if ( pPacket->Hdr.idCmd == CLIP_DATA
410 && vbcl::ipc::packet_verify(&pPacket->Hdr, pPacket->Hdr.cbData))
411 {
412 void *pvData = RTMemAllocZ(pPacket->cbData);
413 idCmd = pPacket->Hdr.idCmd;
414 if (RT_VALID_PTR(pvData))
415 {
416 memcpy(pvData, (uint8_t *)pPacket + sizeof(vbcl::ipc::clipboard::data_packet_t), pPacket->cbData);
417 m_pvClipboardBuf.set((uint64_t)pvData);
418 cbData = pPacket->cbData;
419 m_cbClipboardBuf.set(cbData);
420 }
421 else
422 rc = VERR_NO_MEMORY;
423 }
424 else
425 rc = VERR_WRONG_ORDER;
426
427 RTMemFree(pPacket);
428 }
429
430 VBClLogVerbose(3, "%s: recv_data [sid=%u, cmd=0x%x, cbData=%u], rc=%Rrc\n",
431 m_fServer ? "server" : "client", uSessionId, idCmd, cbData, rc);
432
433 return rc;
434}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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