VirtualBox

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

Last change on this file since 71775 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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