VirtualBox

source: vbox/trunk/src/VBox/ExtPacks/VNC/VBoxVNC.cpp@ 55747

Last change on this file since 55747 was 54380, checked in by vboxsync, 10 years ago

ExtPacks/VNC: fixed a possible crash when the client connects during VM restore (thanks Yonathan Randolph)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.2 KB
Line 
1/* $Id: VBoxVNC.cpp 54380 2015-02-23 11:24:25Z vboxsync $ */
2/** @file
3 * VBoxVNC - VNC VRDE module.
4 */
5
6/*
7 * Contributed by Ivo Smits <[email protected]>, Howard Su and
8 * Christophe Devriese <[email protected]>
9 *
10 * Copyright (C) 2011-2012 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21/*******************************************************************************
22* Header Files *
23*******************************************************************************/
24#define LOG_GROUP LOG_GROUP_VRDE
25#include <VBox/log.h>
26
27#include <iprt/asm.h>
28#include <iprt/alloca.h>
29#include <iprt/ldr.h>
30#include <iprt/param.h>
31#include <iprt/path.h>
32#include <iprt/mem.h>
33#include <iprt/socket.h>
34#include <iprt/stream.h>
35#include <iprt/string.h>
36#include <iprt/thread.h>
37#include <iprt/cpp/utils.h>
38
39#include <VBox/err.h>
40#include <VBox/RemoteDesktop/VRDEOrders.h>
41#include <VBox/RemoteDesktop/VRDE.h>
42
43#include <rfb/rfb.h>
44
45#ifdef LIBVNCSERVER_IPv6
46// enable manually!
47// #define VBOX_USE_IPV6
48#endif
49
50
51/*******************************************************************************
52* Defined Constants And Macros *
53*******************************************************************************/
54#define VNC_SIZEOFRGBA 4
55#define VNC_PASSWORDSIZE 20
56#define VNC_ADDRESSSIZE 60
57#define VNC_PORTSSIZE 20
58#define VNC_ADDRESS_OPTION_MAX 500
59
60
61/*******************************************************************************
62* Structures and Typedefs *
63*******************************************************************************/
64class VNCServerImpl
65{
66public:
67 VNCServerImpl()
68 {
69 mVNCServer = NULL;
70 mFrameBuffer = NULL;
71 mScreenBuffer = NULL;
72 mCursor = NULL;
73 uClients = 0;
74 }
75
76 ~VNCServerImpl()
77 {
78 if (mFrameBuffer)
79 RTMemFree(mFrameBuffer);
80 if (mCursor)
81 rfbFreeCursor(mCursor);
82 RT_ZERO(szVNCPassword);
83 if (mVNCServer)
84 rfbScreenCleanup(mVNCServer);
85 }
86
87 int Init(const VRDEINTERFACEHDR *pCallbacks, void *pvCallback);
88
89 VRDEINTERFACEHDR *GetInterface() { return &Entries.header; }
90
91private:
92 // VNC password
93 char szVNCPassword[VNC_PASSWORDSIZE + 1];
94 // the structure we pass to libvncserver
95 char *apszVNCPasswordStruct[2];
96
97 // VNC related variables
98 rfbScreenInfoPtr mVNCServer;
99 void *mCallback;
100 rfbCursorPtr mCursor;
101 VRDEFRAMEBUFFERINFO FrameInfo;
102 unsigned char *mScreenBuffer;
103 unsigned char *mFrameBuffer;
104 uint32_t uClients;
105 static DECLCALLBACK(enum rfbNewClientAction) rfbNewClientEvent(rfbClientPtr cl);
106 static DECLCALLBACK(void) vncMouseEvent(int buttonMask, int x, int y, rfbClientPtr cl);
107 static void vncKeyboardEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl);
108 static void clientGoneHook(rfbClientPtr cl);
109
110 static uint32_t RGB2BGR(uint32_t c)
111 {
112 c = ((c >> 0) & 0xff) << 16 |
113 ((c >> 8) & 0xff) << 8 |
114 ((c >> 16) & 0xff) << 0;
115
116 return c;
117 }
118
119 int queryVrdeFeature(const char *pszName, char *pszValue, size_t cbValue);
120
121 static VRDEENTRYPOINTS_4 Entries;
122 VRDECALLBACKS_4 *mCallbacks;
123
124 static DECLCALLBACK(void) VRDEDestroy(HVRDESERVER hServer);
125 static DECLCALLBACK(int) VRDEEnableConnections(HVRDESERVER hServer, bool fEnable);
126 static DECLCALLBACK(void) VRDEDisconnect(HVRDESERVER hServer, uint32_t u32ClientId, bool fReconnect);
127 static DECLCALLBACK(void) VRDEResize(HVRDESERVER hServer);
128 static DECLCALLBACK(void) VRDEUpdate(HVRDESERVER hServer, unsigned uScreenId, void *pvUpdate,uint32_t cbUpdate);
129 static DECLCALLBACK(void) VRDEColorPointer(HVRDESERVER hServer, const VRDECOLORPOINTER *pPointer);
130 static DECLCALLBACK(void) VRDEHidePointer(HVRDESERVER hServer);
131 static DECLCALLBACK(void) VRDEAudioSamples(HVRDESERVER hServer, const void *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format);
132 static DECLCALLBACK(void) VRDEAudioVolume(HVRDESERVER hServer, uint16_t u16Left, uint16_t u16Right);
133 static DECLCALLBACK(void) VRDEUSBRequest(HVRDESERVER hServer,
134 uint32_t u32ClientId,
135 void *pvParm,
136 uint32_t cbParm);
137 static DECLCALLBACK(void) VRDEClipboard(HVRDESERVER hServer,
138 uint32_t u32Function,
139 uint32_t u32Format,
140 void *pvData,
141 uint32_t cbData,
142 uint32_t *pcbActualRead);
143 static DECLCALLBACK(void) VRDEQueryInfo(HVRDESERVER hServer,
144 uint32_t index,
145 void *pvBuffer,
146 uint32_t cbBuffer,
147 uint32_t *pcbOut);
148 static DECLCALLBACK(void) VRDERedirect(HVRDESERVER hServer,
149 uint32_t u32ClientId,
150 const char *pszServer,
151 const char *pszUser,
152 const char *pszDomain,
153 const char *pszPassword,
154 uint32_t u32SessionId,
155 const char *pszCookie);
156 static DECLCALLBACK(void) VRDEAudioInOpen(HVRDESERVER hServer,
157 void *pvCtx,
158 uint32_t u32ClientId,
159 VRDEAUDIOFORMAT audioFormat,
160 uint32_t u32SamplesPerBlock);
161 static DECLCALLBACK(void) VRDEAudioInClose(HVRDESERVER hServer,
162 uint32_t u32ClientId);
163};
164
165VRDEENTRYPOINTS_4 VNCServerImpl::Entries = {
166 { VRDE_INTERFACE_VERSION_3, sizeof(VRDEENTRYPOINTS_3) },
167 VNCServerImpl::VRDEDestroy,
168 VNCServerImpl::VRDEEnableConnections,
169 VNCServerImpl::VRDEDisconnect,
170 VNCServerImpl::VRDEResize,
171 VNCServerImpl::VRDEUpdate,
172 VNCServerImpl::VRDEColorPointer,
173 VNCServerImpl::VRDEHidePointer,
174 VNCServerImpl::VRDEAudioSamples,
175 VNCServerImpl::VRDEAudioVolume,
176 VNCServerImpl::VRDEUSBRequest,
177 VNCServerImpl::VRDEClipboard,
178 VNCServerImpl::VRDEQueryInfo,
179 VNCServerImpl::VRDERedirect,
180 VNCServerImpl::VRDEAudioInOpen,
181 VNCServerImpl::VRDEAudioInClose
182};
183
184
185/** Destroy the server instance.
186 *
187 * @param hServer The server instance handle.
188 *
189 * @return IPRT status code.
190 */
191DECLCALLBACK(void) VNCServerImpl::VRDEDestroy(HVRDESERVER hServer)
192{
193 VNCServerImpl *instance = (VNCServerImpl *)hServer;
194 rfbShutdownServer(instance->mVNCServer, TRUE);
195
196 uint32_t port = UINT32_MAX;
197 instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
198 VRDE_SP_NETWORK_BIND_PORT,
199 &port, sizeof(port), NULL);
200 return;
201}
202
203
204/**
205 * Query a feature and store it's value in a user supplied buffer.
206 *
207 * @returns VBox status code.
208 * @param pszName The feature name.
209 * @param pszValue The value buffer. The buffer is not touched at
210 * all on failure.
211 * @param cbValue The size of the output buffer.
212 */
213int VNCServerImpl::queryVrdeFeature(const char *pszName, char *pszValue, size_t cbValue)
214{
215 union
216 {
217 VRDEFEATURE Feat;
218 uint8_t abBuf[VNC_ADDRESS_OPTION_MAX + sizeof(VRDEFEATURE)];
219 } u;
220
221 u.Feat.u32ClientId = 0;
222 int rc = RTStrCopy(u.Feat.achInfo, VNC_ADDRESS_OPTION_MAX, pszName); AssertRC(rc);
223 if (RT_SUCCESS(rc))
224 {
225 uint32_t cbOut = 0;
226 rc = mCallbacks->VRDECallbackProperty(mCallback,
227 VRDE_QP_FEATURE,
228 &u.Feat,
229 VNC_ADDRESS_OPTION_MAX,
230 &cbOut);
231 if (RT_SUCCESS(rc))
232 {
233 size_t cbRet = strlen(u.Feat.achInfo) + 1;
234 if (cbRet <= cbValue)
235 memcpy(pszValue, u.Feat.achInfo, cbRet);
236 else
237 rc = VERR_BUFFER_OVERFLOW;
238 }
239 }
240
241 return rc;
242}
243
244
245/** The server should start to accept clients connections.
246 *
247 * @param hServer The server instance handle.
248 * @param fEnable Whether to enable or disable client connections.
249 * When is false, all existing clients are disconnected.
250 *
251 * @return IPRT status code.
252 */
253DECLCALLBACK(int) VNCServerImpl::VRDEEnableConnections(HVRDESERVER hServer, bool fEnable)
254{
255 VNCServerImpl *instance = (VNCServerImpl *)hServer;
256
257#ifdef LOG_ENABLED
258 // enable logging
259 rfbLogEnable(true);
260#endif
261 LogFlowFunc(("enter\n"));
262
263 // At this point, VRDECallbackFramebufferQuery will not succeed.
264 // Initialize VNC with 640x480 and wait for VRDEResize to get actual size.
265 int dummyWidth = 640, dummyHeight = 480;
266
267 rfbScreenInfoPtr vncServer = rfbGetScreen(0, NULL, dummyWidth, dummyHeight, 8, 3, VNC_SIZEOFRGBA);
268 instance->mVNCServer = vncServer;
269
270 VRDEFRAMEBUFFERINFO info;
271 RT_ZERO(info);
272 info.cWidth = dummyWidth, info.cHeight = dummyHeight;
273 info.cBitsPerPixel = 24;
274 info.pu8Bits = NULL;
275 unsigned char *FrameBuffer = (unsigned char *)RTMemAlloc(info.cWidth * info.cHeight * VNC_SIZEOFRGBA); // RGBA
276 rfbNewFramebuffer(instance->mVNCServer, (char *)FrameBuffer, info.cWidth, info.cHeight, 8, 3, VNC_SIZEOFRGBA);
277 instance->mFrameBuffer = FrameBuffer;
278 instance->mScreenBuffer = (unsigned char *)info.pu8Bits;
279 instance->FrameInfo = info;
280
281 vncServer->serverFormat.redShift = 16;
282 vncServer->serverFormat.greenShift = 8;
283 vncServer->serverFormat.blueShift = 0;
284 vncServer->screenData = (void *)instance;
285 vncServer->desktopName = "VBoxVNC";
286
287#ifndef VBOX_USE_IPV6
288
289 // get listen address
290 char szAddress[VNC_ADDRESSSIZE + 1] = {0};
291 uint32_t cbOut = 0;
292 int rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
293 VRDE_QP_NETWORK_ADDRESS,
294 &szAddress, sizeof(szAddress), &cbOut);
295 Assert(cbOut <= sizeof(szAddress));
296 if (RT_SUCCESS(rc) && szAddress[0])
297 {
298 if (!rfbStringToAddr(szAddress, &vncServer->listenInterface))
299 LogRel(("VNC: could not parse VNC server listen address '%s'\n", szAddress));
300 }
301
302 // get listen port
303 uint32_t port = 0;
304 rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
305 VRDE_QP_NETWORK_PORT,
306 &port, sizeof(port), &cbOut);
307 Assert(cbOut <= sizeof(port));
308 if (RT_SUCCESS(rc) && port != 0)
309 vncServer->port = port;
310 else
311 {
312 const char szFeatName[] = "Property/TCP/Ports";
313 const uint32_t featLen = sizeof(VRDEFEATURE) + RT_MAX(sizeof(VNC_PORTSSIZE), sizeof(szFeatName)) - 1;
314 VRDEFEATURE *feature = (VRDEFEATURE *)RTMemTmpAlloc(featLen);
315 feature->u32ClientId = 0;
316 RTStrCopy(feature->achInfo, featLen - sizeof(VRDEFEATURE) + 1, szFeatName);
317
318 cbOut = featLen;
319 rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback, VRDE_QP_FEATURE, feature, featLen, &cbOut);
320 Assert(cbOut <= featLen);
321
322 if (RT_SUCCESS(rc) && feature->achInfo[0])
323 {
324 rc = RTStrToUInt32Ex(feature->achInfo, NULL, 0, &port);
325 if (RT_FAILURE(rc) || port >= 65535)
326 vncServer->autoPort = 1;
327 else
328 vncServer->port = port;
329 }
330 else
331 vncServer->autoPort = 1;
332
333 RTMemTmpFree(feature);
334 }
335
336 rfbInitServer(vncServer);
337
338 vncServer->newClientHook = rfbNewClientEvent;
339 vncServer->kbdAddEvent = vncKeyboardEvent;
340 vncServer->ptrAddEvent = vncMouseEvent;
341
342 // notify about the actually used port
343 port = vncServer->port;
344 instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
345 VRDE_SP_NETWORK_BIND_PORT,
346 &port, sizeof(port), NULL);
347 LogRel(("VNC: port = %u\n", port));
348#else
349 // with IPv6 from here
350 /*
351
352 This is the deal:
353
354 Four new options are available:
355 - VNCAddress4 -> IPv4 address to use
356 - VNCPort4 -> IPv4 Port to use
357 - VNCAddress6 -> IPv6 address to use
358 - VNCPort6 -> IPv6 port to use
359
360 By default we prefer IPv6 over IPv4.
361
362 The address length can be unlimited as the interface identifier is not
363 limited by any specs - if this is wrong, and someone knows the line
364 and the RFC number, i'd appreciate a message :)
365
366 THE MAXIMUM LENGTH OF THE RETURNED VALUES MUST NOT BE GREATER THAN:
367
368 --> VBOX_ADDRESS_OPTION_MAX <--
369
370 which is defined at the top of this file.
371
372 The way to determine which address to use is as follows:
373
374 1st - get address information from VRDEProperties
375 "TCP/Address"
376 "TCP/Ports"
377
378 2nd - if the address information is IPv4 get VNCAddress6 and VNCPort6
379 2nd - if the address information is IPv6 get VNCAddress4 and VNCPort4
380 2nd - if the address information is EMPTY and TCP/Ports returns 3389,
381 check both, VNCAddress4 and VNCAddress6 as well as the ports.
382 3389 is not a valid VNC port, therefore we assume it's not
383 been set
384
385 If one of the addresses is empty we assume to listen on any
386 interface/address for that protocol. In other words:
387 IPv4: 0.0.0.0
388 IPv6: ::
389
390 2nd - if everything is empty -> listen on all interfaces
391
392 3rd - check if the addresses are valid hand them to libvncserver
393 to open the initial sockets.
394
395 4th - after the sockets have been opened, the used port of the
396 address/protocol in TCP/Address is returned.
397 if TCP/Address is empty, prefer IPv6
398
399 */
400
401 /* ok, now first get the address from VRDE/TCP/Address.
402
403 */
404 // this should be put somewhere else
405 char szIPv6ListenAll[] = "::";
406 char szIPv4ListenAll[] = "0.0.0.0";
407
408 uint32_t uServerPort4 = 0;
409 uint32_t uServerPort6 = 0;
410 uint32_t cbOut = 0;
411 size_t resSize = 0;
412 RTNETADDRTYPE enmAddrType;
413 char *pszVNCAddress6 = NULL;
414 char *pszVNCPort6 = NULL;
415 char *pszServerAddress4 = NULL;
416 char *pszServerAddress6 = NULL;
417 char *pszGetAddrInfo4 = NULL; // used to store the result of RTSocketQueryAddressStr()
418 char *pszGetAddrInfo6 = NULL; // used to store the result of RTSocketQueryAddressStr()
419
420 // get address
421 char *pszTCPAddress = (char *)RTMemTmpAllocZ(VNC_ADDRESS_OPTION_MAX);
422 rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
423 VRDE_QP_NETWORK_ADDRESS,
424 pszTCPAddress,
425 VNC_ADDRESS_OPTION_MAX,
426 &cbOut);
427
428 // get port (range)
429 char *pszTCPPort = (char *)RTMemTmpAllocZ(VNC_ADDRESS_OPTION_MAX);
430 rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
431 VRDE_QP_NETWORK_PORT_RANGE,
432 pszTCPPort,
433 VNC_ADDRESS_OPTION_MAX,
434 &cbOut);
435 Assert(cbOut < VNC_ADDRESS_OPTION_MAX);
436
437 // get tcp ports option from vrde.
438 /** @todo r=bird: Is this intentionally overriding VRDE_QP_NETWORK_PORT_RANGE? */
439 instance->queryVrdeFeature("Property/TCP/Ports", pszTCPPort, VNC_ADDRESS_OPTION_MAX);
440
441 // get VNCAddress4
442 char *pszVNCAddress4 = (char *)RTMemTmpAllocZ(24);
443 instance->queryVrdeFeature("Property/VNCAddress4", pszVNCAddress4, 24);
444
445 // VNCPort4
446 char *pszVNCPort4 = (char *)RTMemTmpAlloc(6);
447 instance->queryVrdeFeature("Property/VNCPort4", pszVNCPort4, 6);
448
449 // VNCAddress6
450 pszVNCAddress6 = (char *) RTMemTmpAllocZ(VNC_ADDRESS_OPTION_MAX);
451 instance->queryVrdeFeature("Property/VNCAddress6", pszVNCAddress6, VNC_ADDRESS_OPTION_MAX);
452
453 // VNCPort6
454 pszVNCPort6 = (char *)RTMemTmpAllocZ(6);
455 instance->queryVrdeFeature("Property/VNCPort6", pszVNCPort6, 6);
456
457
458 if (RTNetIsIPv4AddrStr(pszTCPAddress))
459 {
460 pszServerAddress4 = pszTCPAddress;
461
462 if (strlen(pszTCPPort) > 0)
463 {
464 rc = RTStrToUInt32Ex(pszTCPPort, NULL, 10, &uServerPort4);
465 if (!RT_SUCCESS(rc) || uServerPort4 > 65535)
466 uServerPort4 = 0;
467 }
468
469 if (RTNetIsIPv6AddrStr(pszVNCAddress6))
470 pszServerAddress6 = pszVNCAddress6;
471 else
472 pszServerAddress6 = szIPv6ListenAll;
473
474 if (strlen(pszVNCPort6) > 0)
475 {
476 rc = RTStrToUInt32Ex(pszVNCPort6, NULL, 10, &uServerPort6);
477 if (!RT_SUCCESS(rc) || uServerPort6 > 65535)
478 uServerPort6 = 0;
479
480 }
481
482 }
483
484 if (RTNetIsIPv6AddrStr(pszTCPAddress))
485 {
486 pszServerAddress6 = pszTCPAddress;
487
488 if (strlen(pszTCPPort) > 0)
489 {
490 rc = RTStrToUInt32Ex(pszTCPPort, NULL, 10, &uServerPort6);
491 if (!RT_SUCCESS(rc) || uServerPort6 > 65535)
492 uServerPort6 = 0;
493 }
494
495 if (RTNetIsIPv4AddrStr(pszVNCAddress4))
496 pszServerAddress4 = pszVNCAddress4;
497 else
498 pszServerAddress4 = szIPv4ListenAll;
499
500 if (strlen(pszVNCPort4) > 0)
501 {
502 rc = RTStrToUInt32Ex(pszVNCPort4, NULL, 10, &uServerPort4);
503 if (!RT_SUCCESS(rc) || uServerPort4 > 65535)
504 uServerPort4 = 0;
505
506 }
507 }
508
509 if ((pszServerAddress4 != pszTCPAddress) && (pszServerAddress6 != pszTCPAddress) && (strlen(pszTCPAddress) > 0))
510 {
511 // here we go, we prefer IPv6 over IPv4;
512 resSize = 42;
513 pszGetAddrInfo6 = (char *) RTMemTmpAllocZ(resSize);
514 enmAddrType = RTNETADDRTYPE_IPV6;
515
516 rc = RTSocketQueryAddressStr(pszTCPAddress, pszGetAddrInfo6, &resSize, &enmAddrType);
517 if (RT_SUCCESS(rc))
518 pszServerAddress6 = pszGetAddrInfo6;
519 else
520 {
521 RTMemTmpFree(pszGetAddrInfo6);
522 pszGetAddrInfo6 = NULL;
523 }
524
525 if (!pszServerAddress6)
526 {
527 resSize = 16;
528 pszGetAddrInfo4 = (char *) RTMemTmpAllocZ(resSize);
529 enmAddrType = RTNETADDRTYPE_IPV4;
530
531 rc = RTSocketQueryAddressStr(pszTCPAddress, pszGetAddrInfo4, &resSize, &enmAddrType);
532
533 if (RT_SUCCESS(rc))
534 pszServerAddress4 = pszGetAddrInfo4;
535 else
536 {
537 RTMemTmpFree(pszGetAddrInfo4);
538 pszGetAddrInfo4 = NULL;
539 }
540 }
541 }
542
543 if (!pszServerAddress4 && strlen(pszVNCAddress4) > 0)
544 {
545 resSize = 16;
546 pszGetAddrInfo4 = (char *) RTMemTmpAllocZ(resSize);
547 enmAddrType = RTNETADDRTYPE_IPV4;
548
549 rc = RTSocketQueryAddressStr(pszVNCAddress4, pszGetAddrInfo4, &resSize, &enmAddrType);
550
551 if (RT_SUCCESS(rc))
552 pszServerAddress4 = pszGetAddrInfo4;
553
554 }
555
556 if (!pszServerAddress6 && strlen(pszVNCAddress6) > 0)
557 {
558 resSize = 42;
559 pszGetAddrInfo6 = (char *) RTMemTmpAllocZ(resSize);
560 enmAddrType = RTNETADDRTYPE_IPV6;
561
562 rc = RTSocketQueryAddressStr(pszVNCAddress6, pszGetAddrInfo6, &resSize, &enmAddrType);
563
564 if (RT_SUCCESS(rc))
565 pszServerAddress6 = pszGetAddrInfo6;
566
567 }
568 if (!pszServerAddress4)
569 {
570 if (RTNetIsIPv4AddrStr(pszVNCAddress4))
571 pszServerAddress4 = pszVNCAddress4;
572 else
573 pszServerAddress4 = szIPv4ListenAll;
574 }
575 if (!pszServerAddress6)
576 {
577 if (RTNetIsIPv6AddrStr(pszVNCAddress6))
578 pszServerAddress6 = pszVNCAddress6;
579 else
580 pszServerAddress6 = szIPv6ListenAll;
581 }
582
583 if (pszVNCPort4 && uServerPort4 == 0)
584 {
585 rc = RTStrToUInt32Ex(pszVNCPort4, NULL, 10, &uServerPort4);
586 if (!RT_SUCCESS(rc) || uServerPort4 > 65535)
587 uServerPort4 = 0;
588 }
589
590 if (pszVNCPort6 && uServerPort6 == 0)
591 {
592 rc = RTStrToUInt32Ex(pszVNCPort6, NULL, 10, &uServerPort6);
593 if (!RT_SUCCESS(rc) || uServerPort6 > 65535)
594 uServerPort6 = 0;
595 }
596
597 if (uServerPort4 == 0 || uServerPort6 == 0)
598 vncServer->autoPort = 1;
599 else
600 {
601 vncServer->port = uServerPort4;
602 vncServer->ipv6port = uServerPort6;
603 }
604
605 if (!rfbStringToAddr(pszServerAddress4,&vncServer->listenInterface))
606 LogRel(("VNC: could not parse VNC server listen address IPv4 '%s'\n", pszServerAddress4));
607
608 vncServer->listen6Interface = pszServerAddress6;
609
610 rfbInitServer(vncServer);
611
612 vncServer->newClientHook = rfbNewClientEvent;
613 vncServer->kbdAddEvent = vncKeyboardEvent;
614 vncServer->ptrAddEvent = vncMouseEvent;
615
616 // notify about the actually used port
617 int port = 0;
618 port = vncServer->ipv6port;
619
620 if (vncServer->listen6Sock < 0)
621 {
622 LogRel(("VNC: not able to bind to IPv6 socket with address '%s'\n",pszServerAddress6));
623 port = 0;
624
625 }
626
627 instance->mCallbacks->VRDECallbackProperty(instance->mCallback,
628 VRDE_SP_NETWORK_BIND_PORT,
629 &port, sizeof(port), NULL);
630 LogRel(("VNC: port6 = %u\n", port));
631
632
633 if (pszTCPAddress)
634 {
635 if (pszTCPAddress == pszServerAddress4)
636 pszServerAddress4 = NULL;
637
638 if (pszTCPAddress == pszServerAddress6)
639 pszServerAddress6 = NULL;
640
641 RTMemTmpFree(pszTCPAddress);
642 }
643
644 RTMemTmpFree(pszTCPPort);
645 RTMemTmpFree(pszVNCAddress4);
646 RTMemTmpFree(pszVNCPort4);
647 RTMemTmpFree(pszGetAddrInfo4);
648 RTMemTmpFree(pszVNCAddress6);
649 RTMemTmpFree(pszGetAddrInfo6);
650
651 // with ipv6 to here
652#endif
653 // let's get the password
654 instance->szVNCPassword[0] = '\0';
655 const char szFeatName[] = "Property/VNCPassword";
656 const uint32_t featLen = sizeof(VRDEFEATURE) + RT_MAX(sizeof(instance->szVNCPassword), sizeof(szFeatName)) - 1;
657 VRDEFEATURE *feature = (VRDEFEATURE *)RTMemTmpAlloc(featLen);
658 feature->u32ClientId = 0;
659 RTStrCopy(feature->achInfo, featLen - sizeof(VRDEFEATURE) + 1, szFeatName);
660
661 cbOut = featLen;
662 rc = instance->mCallbacks->VRDECallbackProperty(instance->mCallback, VRDE_QP_FEATURE, feature, featLen, &cbOut);
663 Assert(cbOut <= featLen);
664
665 if (RT_SUCCESS(rc))
666 {
667 RTStrCopy(instance->szVNCPassword, sizeof(instance->szVNCPassword), feature->achInfo);
668 memset(feature->achInfo, '\0', featLen - sizeof(VRDEFEATURE) + 1);
669 LogRel(("VNC: Configuring password\n"));
670
671 instance->apszVNCPasswordStruct[0] = instance->szVNCPassword;
672 instance->apszVNCPasswordStruct[1] = NULL;
673
674 vncServer->authPasswdData = (void *)instance->apszVNCPasswordStruct;
675 vncServer->passwordCheck = rfbCheckPasswordByList;
676 }
677 else
678 LogRel(("VNC: No password result = %Rrc\n", rc));
679
680 RTMemTmpFree(feature);
681
682 rfbRunEventLoop(vncServer, -1, TRUE);
683
684 return VINF_SUCCESS;
685}
686
687/** The server should disconnect the client.
688 *
689 * @param hServer The server instance handle.
690 * @param u32ClientId The client identifier.
691 * @param fReconnect Whether to send a "REDIRECT to the same server" packet to the
692 * client before disconnecting.
693 *
694 * @return IPRT status code.
695 */
696DECLCALLBACK(void) VNCServerImpl::VRDEDisconnect(HVRDESERVER hServer, uint32_t u32ClientId,
697 bool fReconnect)
698{
699}
700
701static inline void convert15To32bpp(uint8_t msb, uint8_t lsb, uint8_t &r, uint8_t &g, uint8_t &b)
702{
703 uint16_t px = lsb << 8 | msb;
704 // RGB 555 (1 bit unused)
705 r = (px >> 7) & 0xf8;
706 g = (px >> 2) & 0xf8;
707 b = (px << 3) & 0xf8;
708}
709
710static inline void convert16To32bpp(uint8_t msb, uint8_t lsb, uint8_t &r, uint8_t &g, uint8_t &b)
711{
712 uint16_t px = lsb << 8 | msb;
713 // RGB 565 (all bits used, 1 extra bit for green)
714 r = (px >> 8) & 0xf8;
715 g = (px >> 3) & 0xfc;
716 b = (px << 3) & 0xf8;
717}
718
719/**
720 * Inform the server that the display was resized.
721 * The server will query information about display
722 * from the application via callbacks.
723 *
724 * @param hServer Handle of VRDE server instance.
725 */
726DECLCALLBACK(void) VNCServerImpl::VRDEResize(HVRDESERVER hServer)
727{
728 VNCServerImpl *instance = (VNCServerImpl *)hServer;
729 VRDEFRAMEBUFFERINFO info;
730 bool fAvail = instance->mCallbacks->VRDECallbackFramebufferQuery(instance->mCallback, 0, &info);
731 if (!fAvail)
732 return;
733
734 LogRel(("VNCServerImpl::VRDEResize to %dx%dx%dbpp\n", info.cWidth, info.cHeight, info.cBitsPerPixel));
735
736 // we always alloc an RGBA buffer
737 unsigned char *FrameBuffer = (unsigned char *)RTMemAlloc(info.cWidth * info.cHeight * VNC_SIZEOFRGBA); // RGBA
738 if (info.cBitsPerPixel == 32 || info.cBitsPerPixel == 24)
739 {
740 // Convert RGB (windows/vbox) to BGR(vnc)
741 uint32_t i, j;
742 for (i = 0, j = 0; i < info.cWidth * info.cHeight * VNC_SIZEOFRGBA; i += VNC_SIZEOFRGBA, j += info.cBitsPerPixel / 8)
743 {
744 unsigned char r = info.pu8Bits[j];
745 unsigned char g = info.pu8Bits[j + 1];
746 unsigned char b = info.pu8Bits[j + 2];
747 FrameBuffer[i] = b;
748 FrameBuffer[i + 1] = g;
749 FrameBuffer[i + 2] = r;
750 }
751 }
752 else if (info.cBitsPerPixel == 16)
753 {
754 uint32_t i, j;
755 for (i = 0, j = 0;
756 i < info.cWidth * info.cHeight * VNC_SIZEOFRGBA;
757 i += VNC_SIZEOFRGBA, j += info.cBitsPerPixel / 8)
758 {
759 convert16To32bpp(info.pu8Bits[j],
760 info.pu8Bits[j + 1],
761 FrameBuffer[i],
762 FrameBuffer[i + 1],
763 FrameBuffer[i + 2]);
764 }
765 }
766 rfbNewFramebuffer(instance->mVNCServer, (char *)FrameBuffer, info.cWidth, info.cHeight, 8, 3, VNC_SIZEOFRGBA);
767
768 void *temp = instance->mFrameBuffer;
769 instance->mFrameBuffer = FrameBuffer;
770 instance->mScreenBuffer = (unsigned char *)info.pu8Bits;
771 instance->FrameInfo = info;
772 if (temp)
773 RTMemFree(temp);
774}
775
776/**
777 * Send a update.
778 *
779 * @param hServer Handle of VRDE server instance.
780 * @param uScreenId The screen index.
781 * @param pvUpdate Pointer to VBoxGuest.h::VRDEORDERHDR structure with extra data.
782 * @param cbUpdate Size of the update data.
783 */
784DECLCALLBACK(void) VNCServerImpl::VRDEUpdate(HVRDESERVER hServer, unsigned uScreenId,
785 void *pvUpdate,uint32_t cbUpdate)
786{
787 char *ptr = (char *)pvUpdate;
788 VNCServerImpl *instance = (VNCServerImpl *)hServer;
789 VRDEORDERHDR *order = (VRDEORDERHDR *)ptr;
790 ptr += sizeof(VRDEORDERHDR);
791 if (order == NULL)
792 {
793 /* Inform the VRDE server that the current display update sequence is
794 * completed. At this moment the framebuffer memory contains a definite
795 * image, that is synchronized with the orders already sent to VRDE client.
796 * The server can now process redraw requests from clients or initial
797 * fullscreen updates for new clients.
798 */
799
800 }
801 else
802 {
803 if (sizeof(VRDEORDERHDR) != cbUpdate)
804 {
805 VRDEORDERCODE *code = (VRDEORDERCODE *)ptr;
806 ptr += sizeof(VRDEORDERCODE);
807
808 switch(code->u32Code)
809 {
810 case VRDE_ORDER_SOLIDRECT:
811 {
812 VRDEORDERSOLIDRECT *solidrect = (VRDEORDERSOLIDRECT *)ptr;
813 rfbFillRect(instance->mVNCServer, solidrect->x, solidrect->y,
814 solidrect->x + solidrect->w, solidrect->y + solidrect->h, RGB2BGR(solidrect->rgb));
815 return;
816 }
817 ///@todo: more orders
818 }
819 }
820
821 uint32_t width = instance->FrameInfo.cWidth;
822 uint32_t bpp = instance->FrameInfo.cBitsPerPixel / 8;
823 uint32_t joff = order->y * width + order->x;
824 uint32_t srcx, srcy, destx, desty;
825 if (instance->FrameInfo.cBitsPerPixel == 32 || instance->FrameInfo.cBitsPerPixel == 24)
826 {
827 for (srcy = joff * bpp, desty = joff * VNC_SIZEOFRGBA;
828 desty < (joff + order->h * width) * VNC_SIZEOFRGBA;
829 srcy += width * bpp, desty += width * VNC_SIZEOFRGBA)
830 {
831 // RGB to BGR
832 for (srcx = srcy, destx = desty;
833 destx < desty + order->w * VNC_SIZEOFRGBA;
834 srcx += bpp, destx += VNC_SIZEOFRGBA)
835 {
836 instance->mFrameBuffer[destx] = instance->mScreenBuffer[srcx + 2];
837 instance->mFrameBuffer[destx + 1] = instance->mScreenBuffer[srcx + 1];
838 instance->mFrameBuffer[destx + 2] = instance->mScreenBuffer[srcx];
839 }
840 }
841 }
842 else if (instance->FrameInfo.cBitsPerPixel == 16)
843 {
844 for (srcy = joff * bpp, desty = joff * VNC_SIZEOFRGBA;
845 desty < (joff + order->h * width) * VNC_SIZEOFRGBA;
846 srcy += width * bpp, desty += width * VNC_SIZEOFRGBA)
847 {
848 for (srcx = srcy, destx = desty;
849 destx < desty + order->w * VNC_SIZEOFRGBA;
850 srcx += bpp, destx += VNC_SIZEOFRGBA)
851 {
852 convert16To32bpp(instance->mScreenBuffer[srcx],
853 instance->mScreenBuffer[srcx + 1],
854 instance->mFrameBuffer[destx],
855 instance->mFrameBuffer[destx + 1],
856 instance->mFrameBuffer[destx + 2]);
857 }
858 }
859 }
860 rfbMarkRectAsModified(instance->mVNCServer, order->x, order->y, order->x+order->w, order->y+order->h);
861 }
862}
863
864
865/**
866 * Set the mouse pointer shape.
867 *
868 * @param hServer Handle of VRDE server instance.
869 * @param pPointer The pointer shape information.
870 */
871DECLCALLBACK(void) VNCServerImpl::VRDEColorPointer(HVRDESERVER hServer,
872 const VRDECOLORPOINTER *pPointer)
873{
874 VNCServerImpl *instance = (VNCServerImpl *)hServer;
875 rfbCursorPtr cursor = (rfbCursorPtr)calloc(sizeof(rfbCursor), 1);
876
877 cursor->width = pPointer->u16Width;
878 cursor->height = pPointer->u16Height;
879
880 unsigned char *mem = (unsigned char *)malloc(pPointer->u16Width * pPointer->u16Height * VNC_SIZEOFRGBA);
881 cursor->richSource = mem;
882
883 unsigned char *maskmem = (unsigned char *)malloc(pPointer->u16Width * pPointer->u16Height);
884 cursor->mask = maskmem;
885
886 unsigned char *mask = (unsigned char *)pPointer + sizeof(VRDECOLORPOINTER);
887
888 for(int i = pPointer->u16Height - 1; i >= 0 ; i--)
889 {
890 for(uint16_t j = 0; j < pPointer->u16Width/8; j ++)
891 {
892 *maskmem = ~(*(mask + i * (pPointer->u16Width / 8) + j));
893 *maskmem++;
894 }
895 }
896 unsigned char *color = (unsigned char *)pPointer + sizeof(VRDECOLORPOINTER) + pPointer->u16MaskLen;
897 for(int i = pPointer->u16Height - 1; i >= 0 ; i--)
898 {
899 for(uint16_t j = 0; j < pPointer->u16Width; j ++)
900 {
901 // put the color value;
902 *(mem++) = *(color + (i * pPointer->u16Width *3 + j * 3 + 2));
903 *(mem++) = *(color + (i * pPointer->u16Width *3 + j * 3 + 1));
904 *(mem++) = *(color + (i * pPointer->u16Width *3 + j * 3));
905 *(mem++) = 0xff;
906 }
907 }
908
909 cursor->xhot = pPointer->u16HotX;
910 cursor->yhot = pPointer->u16HotY;
911
912 rfbSetCursor(instance->mVNCServer, cursor);
913
914 if (instance->mCursor)
915 rfbFreeCursor(instance->mCursor);
916
917 instance->mCursor = cursor;
918}
919
920/**
921 * Hide the mouse pointer.
922 *
923 * @param hServer Handle of VRDE server instance.
924 */
925DECLCALLBACK(void) VNCServerImpl::VRDEHidePointer(HVRDESERVER hServer)
926{
927 VNCServerImpl *instance = (VNCServerImpl *)hServer;
928
929 ///@todo: what's behavior for this. hide doesn't seems right
930 //rfbSetCursor(instance->mVNCServer, NULL);
931}
932
933/**
934 * Queues the samples to be sent to clients.
935 *
936 * @param hServer Handle of VRDE server instance.
937 * @param pvSamples Address of samples to be sent.
938 * @param cSamples Number of samples.
939 * @param format Encoded audio format for these samples.
940 *
941 * @note Initialized to NULL when the application audio callbacks are NULL.
942 */
943DECLCALLBACK(void) VNCServerImpl::VRDEAudioSamples(HVRDESERVER hServer,
944 const void *pvSamples,
945 uint32_t cSamples,
946 VRDEAUDIOFORMAT format)
947{
948}
949
950/**
951 * Sets the sound volume on clients.
952 *
953 * @param hServer Handle of VRDE server instance.
954 * @param left 0..0xFFFF volume level for left channel.
955 * @param right 0..0xFFFF volume level for right channel.
956 *
957 * @note Initialized to NULL when the application audio callbacks are NULL.
958 */
959DECLCALLBACK(void) VNCServerImpl::VRDEAudioVolume(HVRDESERVER hServer,
960 uint16_t u16Left,
961 uint16_t u16Right)
962{
963}
964
965/**
966 * Sends a USB request.
967 *
968 * @param hServer Handle of VRDE server instance.
969 * @param u32ClientId An identifier that allows the server to find the corresponding client.
970 * The identifier is always passed by the server as a parameter
971 * of the FNVRDEUSBCALLBACK. Note that the value is the same as
972 * in the VRDESERVERCALLBACK functions.
973 * @param pvParm Function specific parameters buffer.
974 * @param cbParm Size of the buffer.
975 *
976 * @note Initialized to NULL when the application USB callbacks are NULL.
977 */
978DECLCALLBACK(void) VNCServerImpl::VRDEUSBRequest(HVRDESERVER hServer,
979 uint32_t u32ClientId,
980 void *pvParm,
981 uint32_t cbParm)
982{
983}
984
985/**
986 * Called by the application when (VRDE_CLIPBOARD_FUNCTION_*):
987 * - (0) guest announces available clipboard formats;
988 * - (1) guest requests clipboard data;
989 * - (2) guest responds to the client's request for clipboard data.
990 *
991 * @param hServer The VRDE server handle.
992 * @param u32Function The cause of the call.
993 * @param u32Format Bitmask of announced formats or the format of data.
994 * @param pvData Points to: (1) buffer to be filled with clients data;
995 * (2) data from the host.
996 * @param cbData Size of 'pvData' buffer in bytes.
997 * @param pcbActualRead Size of the copied data in bytes.
998 *
999 * @note Initialized to NULL when the application clipboard callbacks are NULL.
1000 */
1001DECLCALLBACK(void) VNCServerImpl::VRDEClipboard(HVRDESERVER hServer,
1002 uint32_t u32Function,
1003 uint32_t u32Format,
1004 void *pvData,
1005 uint32_t cbData,
1006 uint32_t *pcbActualRead)
1007{
1008}
1009
1010/**
1011 * Query various information from the VRDE server.
1012 *
1013 * @param hServer The VRDE server handle.
1014 * @param index VRDE_QI_* identifier of information to be returned.
1015 * @param pvBuffer Address of memory buffer to which the information must be written.
1016 * @param cbBuffer Size of the memory buffer in bytes.
1017 * @param pcbOut Size in bytes of returned information value.
1018 *
1019 * @remark The caller must check the *pcbOut. 0 there means no information was returned.
1020 * A value greater than cbBuffer means that information is too big to fit in the
1021 * buffer, in that case no information was placed to the buffer.
1022 */
1023DECLCALLBACK(void) VNCServerImpl::VRDEQueryInfo(HVRDESERVER hServer,
1024 uint32_t index,
1025 void *pvBuffer,
1026 uint32_t cbBuffer,
1027 uint32_t *pcbOut)
1028{
1029 VNCServerImpl *instance = (VNCServerImpl *)hServer;
1030 *pcbOut = 0;
1031
1032 switch (index)
1033 {
1034 case VRDE_QI_ACTIVE: /* # of active clients */
1035 case VRDE_QI_NUMBER_OF_CLIENTS: /* # of connected clients */
1036 {
1037 uint32_t cbOut = sizeof(uint32_t);
1038 if (cbBuffer >= cbOut)
1039 {
1040 *pcbOut = cbOut;
1041 *(uint32_t *)pvBuffer = instance->uClients;
1042 }
1043 break;
1044 }
1045 ///@todo lots more queries to implement
1046 default:
1047 break;
1048 }
1049}
1050
1051
1052/**
1053 * The server should redirect the client to the specified server.
1054 *
1055 * @param hServer The server instance handle.
1056 * @param u32ClientId The client identifier.
1057 * @param pszServer The server to redirect the client to.
1058 * @param pszUser The username to use for the redirection.
1059 * Can be NULL.
1060 * @param pszDomain The domain. Can be NULL.
1061 * @param pszPassword The password. Can be NULL.
1062 * @param u32SessionId The ID of the session to redirect to.
1063 * @param pszCookie The routing token used by a load balancer to
1064 * route the redirection. Can be NULL.
1065 */
1066DECLCALLBACK(void) VNCServerImpl::VRDERedirect(HVRDESERVER hServer,
1067 uint32_t u32ClientId,
1068 const char *pszServer,
1069 const char *pszUser,
1070 const char *pszDomain,
1071 const char *pszPassword,
1072 uint32_t u32SessionId,
1073 const char *pszCookie)
1074{
1075}
1076
1077/**
1078 * Audio input open request.
1079 *
1080 * @param hServer Handle of VRDE server instance.
1081 * @param pvCtx To be used in VRDECallbackAudioIn.
1082 * @param u32ClientId An identifier that allows the server to find the corresponding client.
1083 * @param audioFormat Preferred format of audio data.
1084 * @param u32SamplesPerBlock Preferred number of samples in one block of audio input data.
1085 *
1086 * @note Initialized to NULL when the VRDECallbackAudioIn callback is NULL.
1087 */
1088DECLCALLBACK(void) VNCServerImpl::VRDEAudioInOpen(HVRDESERVER hServer,
1089 void *pvCtx,
1090 uint32_t u32ClientId,
1091 VRDEAUDIOFORMAT audioFormat,
1092 uint32_t u32SamplesPerBlock)
1093{
1094}
1095
1096/**
1097 * Audio input close request.
1098 *
1099 * @param hServer Handle of VRDE server instance.
1100 * @param u32ClientId An identifier that allows the server to find the corresponding client.
1101 *
1102 * @note Initialized to NULL when the VRDECallbackAudioIn callback is NULL.
1103 */
1104DECLCALLBACK(void) VNCServerImpl::VRDEAudioInClose(HVRDESERVER hServer,
1105 uint32_t u32ClientId)
1106{
1107}
1108
1109
1110
1111int VNCServerImpl::Init(const VRDEINTERFACEHDR *pCallbacks,
1112 void *pvCallback)
1113{
1114 if (pCallbacks->u64Version == VRDE_INTERFACE_VERSION_3)
1115 {
1116 mCallbacks = (VRDECALLBACKS_4 *)pCallbacks;
1117 mCallback = pvCallback;
1118 }
1119 else if (pCallbacks->u64Version == VRDE_INTERFACE_VERSION_1)
1120 {
1121 ///@todo: this is incorrect and it will cause crash if client call unsupport func.
1122 mCallbacks = (VRDECALLBACKS_4 *)pCallbacks;
1123 mCallback = pvCallback;
1124
1125
1126 // since they are same in order, let's just change header
1127 Entries.header.u64Version = VRDE_INTERFACE_VERSION_1;
1128 Entries.header.u64Size = sizeof(VRDEENTRYPOINTS_1);
1129 }
1130 else
1131 return VERR_VERSION_MISMATCH;
1132
1133 return VINF_SUCCESS;
1134}
1135
1136
1137void VNCServerImpl::vncKeyboardEvent(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
1138{
1139 VNCServerImpl *instance = static_cast<VNCServerImpl *>(cl->screen->screenData);
1140 VRDEINPUTSCANCODE point;
1141
1142 /* Conversion table for key code range 32-127 (which happen to equal the ASCII codes).
1143 * Values 0xe0?? indicate that a 0xe0 scancode will be sent first (extended keys), then code ?? is sent */
1144 static unsigned codes_low[] =
1145 {
1146 // Conversion table for VNC key code range 32-127
1147 0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28, 0x0a, 0x0b, 0x09, 0x0d, 0x33, 0x0c, 0x34, 0x35, //space, !"#$%&'()*+`-./
1148 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x27, 0x27, 0x33, 0x0d, 0x34, 0x35, 0x03, //0123456789:;<=>?@
1149 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, //A-M
1150 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, //N-Z
1151 0x1a, 0x2b, 0x1b, 0x07, 0x0c, 0x29, //[\]^_`
1152 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, //a-m
1153 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, //n-z
1154 0x1a, 0x2b, 0x1b, 0x29 //{|}~
1155 };
1156
1157 int code = -1;
1158 if (keycode < 32)
1159 {
1160 //ASCII control codes.. unused..
1161 }
1162 else if (keycode < 127)
1163 {
1164 //DEL is in high area
1165 code = codes_low[keycode - 32];
1166 }
1167 else if ((keycode & 0xFE00) != 0xFE00)
1168 {
1169 }
1170 else
1171 {
1172 switch(keycode)
1173 {
1174 case 65027: code = 0xe038; break; //AltGr = RAlt
1175 case 65288: code = 0x0e; break; //Backspace
1176 case 65289: code = 0x0f; break; //Tab
1177
1178 case 65293: code = 0x1c; break; //Return
1179 //case 65299: break; Pause/break
1180 case 65300: code = 0x46; break; //ScrollLock
1181 //case 65301: break; SysRq
1182 case 65307: code = 0x01; break; //Escape
1183
1184 case 65360: code = 0xe047; break; //Home
1185 case 65361: code = 0xe04b; break; //Left
1186 case 65362: code = 0xe048; break; //Up
1187 case 65363: code = 0xe04d; break; //Right
1188 case 65364: code = 0xe050; break; //Down
1189 case 65365: code = 0xe049; break; //Page up
1190 case 65366: code = 0xe051; break; //Page down
1191 case 65367: code = 0xe04f; break; //End
1192
1193 //case 65377: break; //Print screen
1194 case 65379: code = 0xe052; break; //Insert
1195
1196 case 65383: code = 0xe05d; break; //Menu
1197 case 65407: code = 0x45; break; //NumLock
1198
1199 case 65421: code = 0xe01c; break; //Numpad return
1200 case 65429: code = 0x47; break; //Numpad home
1201 case 65430: code = 0x4b; break; //Numpad left
1202 case 65431: code = 0x48; break; //Numpad up
1203 case 65432: code = 0x4d; break; //Numpad right
1204 case 65433: code = 0x50; break; //Numpad down
1205 case 65434: code = 0x49; break; //Numpad page up
1206 case 65435: code = 0x51; break; //Numpad page down
1207 case 65436: code = 0x4f; break; //Numpad end
1208 case 65437: code = 0x4c; break; //Numpad begin
1209 case 65438: code = 0x52; break; //Numpad ins
1210 case 65439: code = 0x53; break; //Numpad del
1211 case 65450: code = 0x37; break; //Numpad *
1212 case 65451: code = 0x4e; break; //Numpad +
1213 case 65452: code = 0x53; break; //Numpad separator
1214 case 65453: code = 0x4a; break; //Numpad -
1215 case 65454: code = 0x53; break; //Numpad decimal
1216 case 65455: code = 0xe035; break; //Numpad /
1217 case 65456: code = 0x52; break; //Numpad 0
1218 case 65457: code = 0x4f; break; //Numpad 1
1219 case 65458: code = 0x50; break; //Numpad 2
1220 case 65459: code = 0x51; break; //Numpad 3
1221 case 65460: code = 0x4b; break; //Numpad 4
1222 case 65461: code = 0x4c; break; //Numpad 5
1223 case 65462: code = 0x4d; break; //Numpad 6
1224 case 65463: code = 0x47; break; //Numpad 7
1225 case 65464: code = 0x48; break; //Numpad 8
1226 case 65465: code = 0x49; break; //Numpad 9
1227
1228 case 65470: code = 0x3b; break; //F1
1229 case 65471: code = 0x3c; break; //F2
1230 case 65472: code = 0x3d; break; //F3
1231 case 65473: code = 0x3e; break; //F4
1232 case 65474: code = 0x3f; break; //F5
1233 case 65475: code = 0x40; break; //F6
1234 case 65476: code = 0x41; break; //F7
1235 case 65477: code = 0x42; break; //F8
1236 case 65478: code = 0x43; break; //F9
1237 case 65479: code = 0x44; break; //F10
1238 case 65480: code = 0x57; break; //F11
1239 case 65481: code = 0x58; break; //F12
1240
1241 case 65505: code = 0x2a; break; //Left shift
1242 case 65506: code = 0x36; break; //Right shift
1243 case 65507: code = 0x1d; break; //Left ctrl
1244 case 65508: code = 0xe01d; break; //Right ctrl
1245 case 65509: code = 0x3a; break; //Caps Lock
1246 case 65510: code = 0x3a; break; //Shift Lock
1247 case 65513: code = 0x38; break; //Left Alt
1248 case 65514: code = 0xe038; break; //Right Alt
1249 case 65515: code = 0xe05b; break; //Left windows key
1250 case 65516: code = 0xe05c; break; //Right windows key
1251 case 65535: code = 0xe053; break; //Delete
1252 }
1253 }
1254
1255 if (code == -1)
1256 {
1257 LogRel(("VNC: unhandled keyboard code: down=%d code=%d\n", down, keycode));
1258 return;
1259 }
1260 if (code > 0xff)
1261 {
1262 point.uScancode = (code >> 8) & 0xff;
1263 instance->mCallbacks->VRDECallbackInput(instance->mCallback, VRDE_INPUT_SCANCODE, &point, sizeof(point));
1264 }
1265
1266 point.uScancode = (code & 0xff) | (down ? 0 : 0x80);
1267 instance->mCallbacks->VRDECallbackInput(instance->mCallback, VRDE_INPUT_SCANCODE, &point, sizeof(point));
1268}
1269
1270void VNCServerImpl::vncMouseEvent(int buttonMask, int x, int y, rfbClientPtr cl)
1271{
1272 VNCServerImpl *instance = static_cast<VNCServerImpl *>(cl->screen->screenData);
1273
1274 VRDEINPUTPOINT point;
1275 unsigned button = 0;
1276 if (buttonMask & 1) button |= VRDE_INPUT_POINT_BUTTON1;
1277 if (buttonMask & 2) button |= VRDE_INPUT_POINT_BUTTON3;
1278 if (buttonMask & 4) button |= VRDE_INPUT_POINT_BUTTON2;
1279 if (buttonMask & 8) button |= VRDE_INPUT_POINT_WHEEL_UP;
1280 if (buttonMask & 16) button |= VRDE_INPUT_POINT_WHEEL_DOWN;
1281 point.uButtons = button;
1282 point.x = x;
1283 point.y = y;
1284 instance->mCallbacks->VRDECallbackInput(instance->mCallback, VRDE_INPUT_POINT, &point, sizeof(point));
1285 rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
1286}
1287
1288enum rfbNewClientAction VNCServerImpl::rfbNewClientEvent(rfbClientPtr cl)
1289{
1290 VNCServerImpl *instance = static_cast<VNCServerImpl *>(cl->screen->screenData);
1291
1292 ///@todo: we need auth user here
1293
1294 instance->mCallbacks->VRDECallbackClientConnect(instance->mCallback, (int)cl->sock);
1295 instance->uClients++;
1296
1297 cl->clientGoneHook = clientGoneHook;
1298
1299 return RFB_CLIENT_ACCEPT;
1300}
1301
1302void VNCServerImpl::clientGoneHook(rfbClientPtr cl)
1303{
1304 VNCServerImpl *instance = static_cast<VNCServerImpl *>(cl->screen->screenData);
1305
1306 instance->uClients--;
1307 instance->mCallbacks->VRDECallbackClientDisconnect(instance->mCallback, (int)cl->sock, 0);
1308}
1309
1310VNCServerImpl *g_VNCServer = 0;
1311
1312DECLEXPORT(int) VRDECreateServer(const VRDEINTERFACEHDR *pCallbacks,
1313 void *pvCallback,
1314 VRDEINTERFACEHDR **ppEntryPoints,
1315 HVRDESERVER *phServer)
1316{
1317 if (!g_VNCServer)
1318 {
1319 g_VNCServer = new VNCServerImpl();
1320 }
1321
1322 int rc = g_VNCServer->Init(pCallbacks, pvCallback);
1323
1324 if (RT_SUCCESS(rc))
1325 {
1326 *ppEntryPoints = g_VNCServer->GetInterface();
1327 *phServer = (HVRDESERVER)g_VNCServer;
1328 }
1329
1330 return rc;
1331}
1332
1333static const char * const supportedProperties[] =
1334{
1335 "TCP/Ports",
1336 "TCP/Address",
1337 NULL
1338};
1339
1340DECLEXPORT(const char * const *) VRDESupportedProperties(void)
1341{
1342 LogFlowFunc(("enter\n"));
1343 return supportedProperties;
1344}
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