VirtualBox

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

Last change on this file since 47550 was 43316, checked in by vboxsync, 12 years ago

4.2.0 GA

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