VirtualBox

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

Last change on this file since 58987 was 57658, checked in by vboxsync, 9 years ago

VNC: build fix

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