vncClient.cpp
Upload User: sbftbdw
Upload Date: 2007-01-03
Package Size: 379k
Code Size: 34k
Category:

Remote Control

Development Platform:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // vncClient.cpp
  24. // The per-client object.  This object takes care of all per-client stuff,
  25. // such as socket input and buffering of updates.
  26. // vncClient class handles the following functions:
  27. // - Recieves requests from the connected client and
  28. //   handles them
  29. // - Handles incoming updates properly, using a vncBuffer
  30. //   object to keep track of screen changes
  31. // It uses a vncBuffer and is passed the vncDesktop and
  32. // vncServer to communicate with.
  33. // Includes
  34. #include "stdhdrs.h"
  35. #include <omnithread.h>
  36. // Custom
  37. #include "vncClient.h"
  38. #include "VSocket.h"
  39. #include "vncDesktop.h"
  40. #include "vncRegion.h"
  41. #include "vncBuffer.h"
  42. #include "vncService.h"
  43. #include "vncPasswd.h"
  44. // #include "rfb.h"
  45. // vncClient thread class
  46. class vncClientThread : public omni_thread
  47. {
  48. public:
  49. // Init
  50. virtual BOOL Init(vncClient *client,
  51. vncServer *server,
  52. VSocket *socket,
  53. BOOL auth);
  54. // Sub-Init routines
  55. virtual BOOL InitVersion();
  56. virtual BOOL InitAuthenticate();
  57. // The main thread function
  58. virtual void run(void *arg);
  59. protected:
  60. virtual ~vncClientThread();
  61. // Fields
  62. protected:
  63. VSocket *m_socket;
  64. vncServer *m_server;
  65. vncClient *m_client;
  66. BOOL m_auth;
  67. };
  68. vncClientThread::~vncClientThread()
  69. {
  70. // If we have a client object then delete it
  71. if (m_client != NULL)
  72. delete m_client;
  73. }
  74. BOOL
  75. vncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOOL auth)
  76. {
  77. // Save the server pointer and window handle
  78. m_server = server;
  79. m_socket = socket;
  80. m_client = client;
  81. m_auth = auth;
  82. // Start the thread
  83. start();
  84. return TRUE;
  85. }
  86. BOOL
  87. vncClientThread::InitVersion()
  88. {
  89. // Generate the server's protocol version
  90. rfbProtocolVersionMsg protocolMsg;
  91. sprintf((char *)protocolMsg,
  92. rfbProtocolVersionFormat,
  93. rfbProtocolMajorVersion,
  94. rfbProtocolMinorVersion);
  95. // Send the protocol message
  96. if (!m_socket->SendExact((char *)&protocolMsg, sz_rfbProtocolVersionMsg))
  97. return FALSE;
  98. // Now, get the client's protocol version
  99. rfbProtocolVersionMsg protocol_ver;
  100. protocol_ver[12] = 0;
  101. if (!m_socket->ReadExact((char *)&protocol_ver, sz_rfbProtocolVersionMsg))
  102. return FALSE;
  103. // Check the protocol version
  104. int major, minor;
  105. sscanf((char *)&protocol_ver, rfbProtocolVersionFormat, &major, &minor);
  106. if (major != rfbProtocolMajorVersion)
  107. return FALSE;
  108. return TRUE;
  109. }
  110. BOOL
  111. vncClientThread::InitAuthenticate()
  112. {
  113. // Retrieve the local password
  114. char password[MAXPWLEN];
  115. m_server->GetPassword(password);
  116. vncPasswd::ToText plain(password);
  117. // By default we disallow passwordless workstations!
  118. if ((strlen(plain) == 0) && m_server->AuthRequired())
  119. {
  120. log.Print(LL_CONNERR, VNCLOG("no password specified for server - client rejectedn"));
  121. // Send an error message to the client
  122. CARD32 auth_val = Swap32IfLE(rfbConnFailed);
  123. char *errmsg =
  124. "This server does not have a valid password enabled.  "
  125. "Until a password is set, incoming connections cannot be accepted.";
  126. CARD32 errlen = Swap32IfLE(strlen(errmsg));
  127. if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
  128. return FALSE;
  129. if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))
  130. return FALSE;
  131. m_socket->SendExact(errmsg, strlen(errmsg));
  132. return FALSE;
  133. }
  134. // By default we filter out local loop connections, because they're pointless
  135. if (!m_server->LoopbackOk())
  136. {
  137. char *localname = strdup(m_socket->GetSockName());
  138. char *remotename = strdup(m_socket->GetPeerName());
  139. // Check that the local & remote names are different!
  140. if ((localname != NULL) && (remotename != NULL))
  141. {
  142. BOOL ok = strcmp(localname, remotename) != 0;
  143. if (localname != NULL)
  144. free(localname);
  145. if (remotename != NULL)
  146. free(remotename);
  147. if (!ok)
  148. {
  149. log.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client rejectedn"));
  150. // Send an error message to the client
  151. CARD32 auth_val = Swap32IfLE(rfbConnFailed);
  152. char *errmsg = "Local loop-back connections are disabled.";
  153. CARD32 errlen = Swap32IfLE(strlen(errmsg));
  154. if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
  155. return FALSE;
  156. if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))
  157. return FALSE;
  158. m_socket->SendExact(errmsg, strlen(errmsg));
  159. return FALSE;
  160. }
  161. }
  162. }
  163. // Authenticate the connection, if required
  164. if (m_auth || (strlen(plain) == 0))
  165. {
  166. // Send no-auth-required message
  167. CARD32 auth_val = Swap32IfLE(rfbNoAuth);
  168. if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
  169. return FALSE;
  170. }
  171. else
  172. {
  173. // Send auth-required message
  174. CARD32 auth_val = Swap32IfLE(rfbVncAuth);
  175. if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
  176. return FALSE;
  177. BOOL auth_ok = TRUE;
  178. {
  179. // Now create a 16-byte challenge
  180. char challenge[16];
  181. vncRandomBytes((BYTE *)&challenge);
  182. // Send the challenge to the client
  183. if (!m_socket->SendExact(challenge, sizeof(challenge)))
  184. return FALSE;
  185. // Read the response
  186. char response[16];
  187. if (!m_socket->ReadExact(response, sizeof(response)))
  188. return FALSE;
  189. // Encrypt the challenge bytes
  190. vncEncryptBytes((BYTE *)&challenge, plain);
  191. // Compare them to the response
  192. for (int i=0; i<sizeof(challenge); i++)
  193. {
  194. if (challenge[i] != response[i])
  195. {
  196. auth_ok = FALSE;
  197. break;
  198. }
  199. }
  200. }
  201. // Did the authentication work?
  202. CARD32 authmsg;
  203. if (!auth_ok)
  204. {
  205. log.Print(LL_CONNERR, VNCLOG("authentication failedn"));
  206. authmsg = Swap32IfLE(rfbVncAuthFailed);
  207. m_socket->SendExact((char *)&authmsg, sizeof(authmsg));
  208. return FALSE;
  209. }
  210. else
  211. {
  212. // Tell the client we're ok
  213. authmsg = Swap32IfLE(rfbVncAuthOK);
  214. if (!m_socket->SendExact((char *)&authmsg, sizeof(authmsg)))
  215. return FALSE;
  216. }
  217. }
  218. // Read the client's initialisation message
  219. rfbClientInitMsg client_ini;
  220. if (!m_socket->ReadExact((char *)&client_ini, sz_rfbClientInitMsg))
  221. return FALSE;
  222. // If the client wishes to have exclusive access then remove other clients
  223. if (!client_ini.shared)
  224. {
  225. // Which client takes priority, existing or incoming?
  226. if (m_server->ConnectPriority() < 1)
  227. {
  228. // Incoming
  229. log.Print(LL_INTINFO, VNCLOG("non-shared connection - disconnecting old clientsn"));
  230. m_server->KillAll();
  231. } else if (m_server->ConnectPriority() > 1)
  232. {
  233. // Existing
  234. if (m_server->AuthClientCount() > 0)
  235. {
  236. log.Print(LL_CLIENTS, VNCLOG("connections already exist - client rejectedn"));
  237. return FALSE;
  238. }
  239. }
  240. }
  241. // Tell the server that this client is ok
  242. return m_server->Authenticated(m_client->GetClientId());
  243. }
  244. void
  245. ClearKeyState(BYTE key)
  246. {
  247. // This routine is used by the VNC client handler to clear the
  248. // CAPSLOCK, NUMLOCK and SCROLL-LOCK states.
  249. BYTE keyState[256];
  250. GetKeyboardState((LPBYTE)&keyState);
  251. if(keyState[key] & 1)
  252. {
  253. // Simulate the key being pressed
  254. keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY, 0);
  255. // Simulate it being release
  256. keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  257. }
  258. }
  259. void
  260. vncClientThread::run(void *arg)
  261. {
  262. // All this thread does is go into a socket-recieve loop,
  263. // waiting for stuff on the given socket
  264. // IMPORTANT : ALWAYS call RemoveClient on the server before quitting
  265. // this thread.
  266. log.Print(LL_CLIENTS, VNCLOG("client connected : %sn"), m_client->GetClientName());
  267. // LOCK INITIAL SETUP
  268. // This prevents other threads interfering
  269. { omni_mutex_lock l(m_client->m_regionLock);
  270. // GET PROTOCOL VERSION
  271. if (!InitVersion())
  272. {
  273. m_server->RemoveClient(m_client->GetClientId());
  274. return;
  275. }
  276. log.Print(LL_INTINFO, VNCLOG("negotiated versionn"));
  277. // AUTHENTICATE LINK
  278. if (!InitAuthenticate())
  279. {
  280. m_server->RemoveClient(m_client->GetClientId());
  281. return;
  282. }
  283. log.Print(LL_INTINFO, VNCLOG("authenticated connectionn"));
  284. // INIT PIXEL FORMAT
  285. // Get the screen format
  286. m_client->m_fullscreen = m_client->m_buffer->GetSize();
  287. // Create the quarter-screen rectangle
  288. m_client->m_qtrscreen.left = 0;
  289. m_client->m_qtrscreen.top = 0;
  290. m_client->m_qtrscreen.right = m_client->m_fullscreen.right/2;
  291. m_client->m_qtrscreen.bottom = m_client->m_fullscreen.bottom/2;
  292. // Get the name of this desktop
  293. char desktopname[MAX_COMPUTERNAME_LENGTH+1];
  294. DWORD desktopnamelen = MAX_COMPUTERNAME_LENGTH + 1;
  295. if (GetComputerName(desktopname, &desktopnamelen))
  296. {
  297. // Make the name lowercase
  298. for (int x=0; x<strlen(desktopname); x++)
  299. {
  300. desktopname[x] = tolower(desktopname[x]);
  301. }
  302. }
  303. else
  304. {
  305. strcpy(desktopname, "WinVNC");
  306. }
  307. // Send the server format message to the client
  308. rfbServerInitMsg server_ini;
  309. server_ini.format = m_client->m_buffer->GetLocalFormat();
  310. // Endian swaps
  311. server_ini.framebufferWidth = Swap16IfLE(m_client->m_fullscreen.right);
  312. server_ini.framebufferHeight = Swap16IfLE(m_client->m_fullscreen.bottom);
  313. server_ini.format.redMax = Swap16IfLE(server_ini.format.redMax);
  314. server_ini.format.greenMax = Swap16IfLE(server_ini.format.greenMax);
  315. server_ini.format.blueMax = Swap16IfLE(server_ini.format.blueMax);
  316. server_ini.nameLength = Swap32IfLE(strlen(desktopname));
  317. if (!m_socket->SendExact((char *)&server_ini, sizeof(server_ini)))
  318. {
  319. m_server->RemoveClient(m_client->GetClientId());
  320. return;
  321. }
  322. if (!m_socket->SendExact(desktopname, strlen(desktopname)))
  323. {
  324. m_server->RemoveClient(m_client->GetClientId());
  325. return;
  326. }
  327. log.Print(LL_INTINFO, VNCLOG("sent pixel format to clientn"));
  328. } // We are past the critical setup section, so free the region lock
  329. // Add a fullscreen update to the client's update list
  330. m_client->UpdateRect(m_client->m_fullscreen);
  331. // Clear the CapsLock and NumLock keys
  332. if (m_client->m_keyboardenabled)
  333. {
  334. ClearKeyState(VK_CAPITAL);
  335. ClearKeyState(VK_NUMLOCK);
  336. ClearKeyState(VK_SCROLL);
  337. }
  338. // MAIN LOOP
  339. BOOL connected = TRUE;
  340. while (connected)
  341. {
  342. rfbClientToServerMsg msg;
  343. // Ensure that we're running in the correct desktop
  344. if (!vncService::InputDesktopSelected())
  345. if (!vncService::SelectDesktop(NULL))
  346. break;
  347. // Try to read a message ID
  348. if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type)))
  349. {
  350. connected = FALSE;
  351. break;
  352. }
  353. // What to do is determined by the message id
  354. switch(msg.type)
  355. {
  356. case rfbSetPixelFormat:
  357. // Read the rest of the message:
  358. if (!m_socket->ReadExact(((char *) &msg)+1, sz_rfbSetPixelFormatMsg-1))
  359. {
  360. connected = FALSE;
  361. break;
  362. }
  363. // Swap the relevant bits.
  364. msg.spf.format.redMax = Swap16IfLE(msg.spf.format.redMax);
  365. msg.spf.format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
  366. msg.spf.format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
  367. { omni_mutex_lock l(m_client->m_regionLock);
  368. // Tell the buffer object of the change
  369. if (!m_client->m_buffer->SetClientFormat(msg.spf.format))
  370. {
  371. log.Print(LL_CONNERR, VNCLOG("remote pixel format invalidn"));
  372. connected = FALSE;
  373. }
  374. // Set the palette-changed flag, just in case...
  375. m_client->m_palettechanged = TRUE;
  376. }
  377. break;
  378. case rfbSetEncodings:
  379. // Read the rest of the message:
  380. if (!m_socket->ReadExact(((char *) &msg)+1, sz_rfbSetEncodingsMsg-1))
  381. {
  382. connected = FALSE;
  383. break;
  384. }
  385. // Read in the preferred encodings
  386. msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
  387. {
  388. int x;
  389. BOOL encoding_set = FALSE;
  390. { omni_mutex_lock l(m_client->m_regionLock);
  391. // By default, don't use copyrect!
  392. m_client->m_copyrect_use = FALSE;
  393. }
  394. for (x=0; x<msg.se.nEncodings; x++)
  395. {
  396. CARD32 encoding;
  397. // Read an encoding in
  398. if (!m_socket->ReadExact((char *)&encoding, sizeof(encoding)))
  399. {
  400. connected = FALSE;
  401. break;
  402. }
  403. // Is this the CopyRect encoding (a special case)?
  404. if (Swap32IfLE(encoding) == rfbEncodingCopyRect)
  405. { omni_mutex_lock l(m_client->m_regionLock);
  406. // Client wants us to use CopyRect
  407. m_client->m_copyrect_use = TRUE;
  408. continue;
  409. }
  410. // Have we already found a suitable encoding?
  411. if (!encoding_set)
  412. { omni_mutex_lock l(m_client->m_regionLock);
  413. // No, so try the buffer to see if this encoding will work...
  414. if (m_client->m_buffer->SetEncoding(Swap32IfLE(encoding)))
  415. encoding_set = TRUE;
  416. }
  417. }
  418. // If no encoding worked then default to RAW!
  419. if (!encoding_set)
  420. {
  421. omni_mutex_lock l(m_client->m_regionLock);
  422. log.Print(LL_INTINFO, VNCLOG("defaulting to raw encodern"));
  423. if (!m_client->m_buffer->SetEncoding(Swap32IfLE(rfbEncodingRaw)))
  424. {
  425. log.Print(LL_INTERR, VNCLOG("failed to select raw encoder!n"));
  426. connected = FALSE;
  427. }
  428. }
  429. }
  430. break;
  431. case rfbFramebufferUpdateRequest:
  432. // Read the rest of the message:
  433. if (!m_socket->ReadExact(((char *) &msg)+1, sz_rfbFramebufferUpdateRequestMsg-1))
  434. {
  435. connected = FALSE;
  436. break;
  437. }
  438. {
  439. RECT update;
  440. // Get the specified rectangle as the region to send updates for.
  441. update.left = Swap16IfLE(msg.fur.x);
  442. update.top = Swap16IfLE(msg.fur.y);
  443. update.right = update.left + Swap16IfLE(msg.fur.w);
  444. update.bottom = update.top + Swap16IfLE(msg.fur.h);
  445. { omni_mutex_lock l(m_client->m_regionLock);
  446. // Set the update-wanted flag to true
  447. m_client->m_updatewanted = TRUE;
  448. // Clip the rectangle to the screen
  449. if (IntersectRect(&update, &update, &m_client->m_fullscreen))
  450. {
  451. // Is this request for an incremental region?
  452. if (msg.fur.incremental)
  453. {
  454. // Yes, so add it to the incremental region
  455. m_client->m_incr_rgn.AddRect(update);
  456. }
  457. else
  458. {
  459. // No, so add it to the full update region
  460. m_client->m_full_rgn.AddRect(update);
  461. // Disable any pending CopyRect
  462. m_client->m_copyrect_set = FALSE;
  463. }
  464. }
  465. // Trigger an update
  466. m_server->RequestUpdate();
  467. }
  468. }
  469. break;
  470. case rfbKeyEvent:
  471. // Read the rest of the message:
  472. if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbKeyEventMsg-1))
  473. {
  474. if (m_client->m_keyboardenabled)
  475. {
  476. msg.ke.key = Swap32IfLE(msg.ke.key);
  477. // Get the keymapper to do the work
  478. m_client->m_keymap.DoXkeysym(msg.ke.key, msg.ke.down);
  479. m_client->m_remoteevent = TRUE;
  480. }
  481. }
  482. break;
  483. case rfbPointerEvent:
  484. // Read the rest of the message:
  485. if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbPointerEventMsg-1))
  486. {
  487. if (m_client->m_pointerenabled)
  488. {
  489. // Convert the coords to Big Endian
  490. msg.pe.x = Swap16IfLE(msg.pe.x);
  491. msg.pe.y = Swap16IfLE(msg.pe.y);
  492. // Work out the flags for this event
  493. DWORD flags = MOUSEEVENTF_ABSOLUTE;
  494. if (msg.pe.x != m_client->m_ptrevent.x ||
  495. msg.pe.y != m_client->m_ptrevent.y)
  496. flags |= MOUSEEVENTF_MOVE;
  497. if ( (msg.pe.buttonMask & rfbButton1Mask) != 
  498. (m_client->m_ptrevent.buttonMask & rfbButton1Mask) )
  499. {
  500.     if (GetSystemMetrics(SM_SWAPBUTTON))
  501. flags |= (msg.pe.buttonMask & rfbButton1Mask) 
  502.     ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
  503.     else
  504. flags |= (msg.pe.buttonMask & rfbButton1Mask) 
  505.     ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
  506. }
  507. if ( (msg.pe.buttonMask & rfbButton2Mask) != 
  508. (m_client->m_ptrevent.buttonMask & rfbButton2Mask) )
  509. {
  510. flags |= (msg.pe.buttonMask & rfbButton2Mask) 
  511.     ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
  512. }
  513. if ( (msg.pe.buttonMask & rfbButton3Mask) != 
  514. (m_client->m_ptrevent.buttonMask & rfbButton3Mask) )
  515. {
  516.     if (GetSystemMetrics(SM_SWAPBUTTON))
  517. flags |= (msg.pe.buttonMask & rfbButton3Mask) 
  518.     ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
  519.     else
  520. flags |= (msg.pe.buttonMask & rfbButton3Mask) 
  521.     ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
  522. }
  523. // Generate coordinate values
  524. unsigned long x = (msg.pe.x *  65535) / (m_client->m_fullscreen.right);
  525. unsigned long y = (msg.pe.y * 65535) / (m_client->m_fullscreen.bottom);
  526. // Do the pointer event
  527. ::mouse_event(flags, (DWORD) x, (DWORD) y, 0, 0);
  528. // Save the old position
  529. m_client->m_ptrevent = msg.pe;
  530. // Flag that a remote event occurred
  531. m_client->m_remoteevent = TRUE;
  532. // Flag that the mouse moved
  533. m_client->UpdateMouse();
  534. // Trigger an update
  535. m_server->RequestUpdate();
  536. }
  537. }
  538. break;
  539. case rfbClientCutText:
  540. // Read the rest of the message:
  541. if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbClientCutTextMsg-1))
  542. {
  543. // Allocate storage for the text
  544. const length = Swap32IfLE(msg.cct.length);
  545. char *text = new char [length+1];
  546. if (text == NULL)
  547. break;
  548. // Read in the text
  549. if (!m_socket->ReadExact(text, length))
  550. break;
  551. text[length] = 0;
  552. // Get the server to update the local clipboard
  553. m_server->UpdateLocalClipText(text);
  554. // Free the clip text we read
  555. delete [] text;
  556. }
  557. break;
  558. default:
  559. // Unknown message, so fail!
  560. connected = FALSE;
  561. }
  562. }
  563. // Quit this thread.  This will automatically delete the thread and the
  564. // associated client.
  565. log.Print(LL_CLIENTS, VNCLOG("client disconnectedn"));
  566. // Remove the client from the server, just in case!
  567. m_server->RemoveClient(m_client->GetClientId());
  568. }
  569. // The vncClient itself
  570. vncClient::vncClient()
  571. {
  572. log.Print(LL_INTINFO, VNCLOG("vncClient() executing...n"));
  573. m_socket = NULL;
  574. m_buffer = NULL;
  575. m_mousemoved = FALSE;
  576. m_ptrevent.buttonMask = 0;
  577. m_ptrevent.x = 0;
  578. m_ptrevent.y=0;
  579. m_thread = NULL;
  580. m_updatewanted = FALSE;
  581. m_palettechanged = FALSE;
  582. m_copyrect_set = FALSE;
  583. m_pollingcycle = 0;
  584. m_remoteevent = FALSE;
  585. }
  586. vncClient::~vncClient()
  587. {
  588. log.Print(LL_INTINFO, VNCLOG("~vncClient() executing...n"));
  589. // We now know the thread is dead, so we can clean up
  590. // If we have a socket then kill it
  591. if (m_socket != NULL)
  592. {
  593. log.Print(LL_INTINFO, VNCLOG("deleting socketn"));
  594. delete m_socket;
  595. m_socket = NULL;
  596. }
  597. // Kill the screen buffer
  598. if (m_buffer != NULL)
  599. {
  600. log.Print(LL_INTINFO, VNCLOG("deleting buffern"));
  601. delete m_buffer;
  602. m_buffer = NULL;
  603. }
  604. }
  605. // Init
  606. BOOL
  607. vncClient::Init(vncServer *server,
  608. VSocket *socket,
  609. BOOL auth,
  610. vncClientId newid)
  611. {
  612. // Save the server id;
  613. m_server = server;
  614. // Save the socket
  615. m_socket = socket;
  616. // Save the client id
  617. m_id = newid;
  618. // Spawn the child thread here
  619. m_thread = new vncClientThread;
  620. if (m_thread == NULL)
  621. return FALSE;
  622. return ((vncClientThread *)m_thread)->Init(this, m_server, m_socket, auth);
  623. return FALSE;
  624. }
  625. void
  626. vncClient::Kill()
  627. {
  628. // Close the socket
  629. if (m_socket != NULL)
  630. m_socket->Close();
  631. }
  632. // Client manipulation functions for use by the server
  633. void
  634. vncClient::SetBuffer(vncBuffer *buffer)
  635. {
  636. // Until authenticated, the client object has no access
  637. // to the screen buffer.  This means that there only need
  638. // be a buffer when there's at least one authenticated client.
  639. m_buffer = buffer;
  640. }
  641. // Update handling functions
  642. void
  643. vncClient::PollWindow(HWND hwnd)
  644. {
  645. BOOL poll = TRUE;
  646. // Are we set to low-load polling?
  647. if (m_server->PollOnEventOnly())
  648. {
  649. // Yes, so only poll if the remote user has done something
  650. if (!m_remoteevent)
  651. poll = FALSE;
  652. }
  653. // Does the client want us to poll only console windows?
  654. if (m_server->PollConsoleOnly())
  655. {
  656. char classname[20];
  657. // Yes, so check that this is a console window...
  658. if (GetClassName(hwnd, classname, sizeof(classname)))
  659. if ((strcmp(classname, "tty") != 0) &&
  660. (strcmp(classname, "ConsoleWindowClass") != 0))
  661. poll = FALSE;
  662. }
  663. // Are we still wanting to poll this window?
  664. if (poll)
  665. {
  666. RECT rect;
  667. // Get the rectangle
  668. if (GetWindowRect(hwnd, &rect))
  669. m_changed_rgn.AddRect(rect);
  670. }
  671. }
  672. void
  673. vncClient::TriggerUpdate()
  674. {
  675. // Lock the updates stored so far
  676. omni_mutex_lock l(m_regionLock);
  677. if (m_updatewanted)
  678. {
  679. // Handle the three polling modes
  680. if (m_server->PollFullScreen())
  681. {
  682. RECT rect;
  683. rect.left = (m_pollingcycle % 2) * m_qtrscreen.right;
  684. rect.right = rect.left + m_qtrscreen.right;
  685. rect.top = (m_pollingcycle / 2) * m_qtrscreen.bottom;
  686. rect.bottom = rect.top + m_qtrscreen.bottom;
  687. m_changed_rgn.AddRect(rect);
  688. m_pollingcycle = (m_pollingcycle + 1) % 4;
  689. }
  690. if (m_server->PollForeground())
  691. {
  692. // Get the window rectangle for the currently selected window
  693. HWND hwnd = GetForegroundWindow();
  694. if (hwnd != NULL)
  695. PollWindow(hwnd);
  696. }
  697. if (m_server->PollUnderCursor())
  698. {
  699. // Find the mouse position
  700. POINT mousepos;
  701. if (GetCursorPos(&mousepos))
  702. {
  703. // Find the window under the mouse
  704. HWND hwnd = WindowFromPoint(mousepos);
  705. if (hwnd != NULL)
  706. PollWindow(hwnd);
  707. }
  708. }
  709. // Clear the remote event flag
  710. m_remoteevent = FALSE;
  711. // Send an update if one is waiting
  712. if (!m_changed_rgn.IsEmpty() ||
  713. !m_full_rgn.IsEmpty() ||
  714. m_copyrect_set)
  715. {
  716. // Has the palette changed?
  717. if (m_palettechanged)
  718. {
  719. m_palettechanged = FALSE;
  720. if (!SendPalette())
  721. return;
  722. }
  723. // Now send the update
  724. m_updatewanted = !SendUpdate();
  725. }
  726. }
  727. }
  728. void
  729. vncClient::UpdateMouse()
  730. {
  731. omni_mutex_lock l(m_regionLock);
  732. if (!m_mousemoved)
  733. {
  734. if (IntersectRect(&m_oldmousepos, &m_oldmousepos, &m_fullscreen))
  735. m_changed_rgn.AddRect(m_oldmousepos);
  736. m_mousemoved = TRUE;
  737. }
  738. }
  739. void
  740. vncClient::UpdateRect(RECT &rect)
  741. {
  742. // Add the rectangle to the update region
  743. if (IsRectEmpty(&rect))
  744. return;
  745. if (IntersectRect(&rect, &rect, &m_fullscreen))
  746. { omni_mutex_lock l(m_regionLock);
  747. m_changed_rgn.AddRect(rect);
  748. }
  749. }
  750. void
  751. vncClient::UpdateRegion(vncRegion &region)
  752. {
  753. // Merge our current update region with the supplied one
  754. if (region.IsEmpty())
  755. return;
  756. { omni_mutex_lock l(m_regionLock);
  757. // Merge the two
  758. vncRegion dummy;
  759. dummy.AddRect(m_fullscreen);
  760. region.Intersect(dummy);
  761. m_changed_rgn.Combine(region);
  762. }
  763. }
  764. void
  765. vncClient::CopyRect(RECT &dest, POINT &source)
  766. {
  767. // If copyrect is disabled then just redraw the region!
  768. if (!m_copyrect_use)
  769. {
  770. UpdateRect(dest);
  771. return;
  772. }
  773. { omni_mutex_lock l(m_regionLock);
  774. // Clip the destination to the screen
  775. RECT destrect;
  776. if (!IntersectRect(&destrect, &dest, &m_fullscreen))
  777. return;
  778. // Adjust the source correspondingly
  779. source.x = source.x + (destrect.left - dest.left);
  780. source.y = source.y + (destrect.top - dest.top);
  781. // Work out the source rectangle
  782. RECT srcrect;
  783. // Is this a continuation of an earlier window drag?
  784. if (m_copyrect_set &&
  785. ((source.x == m_copyrect_rect.left) && (source.y == m_copyrect_rect.top)))
  786. {
  787. // Yes, so use the old source position
  788. srcrect.left = m_copyrect_src.x;
  789. srcrect.top = m_copyrect_src.y;
  790. }
  791. else
  792. {
  793. // No, so use this source position
  794. srcrect.left = source.x;
  795. srcrect.top = source.y;
  796. }
  797. // And fill out the right & bottom using the dest rect
  798. srcrect.right = destrect.right-destrect.left + srcrect.left;
  799. srcrect.bottom = destrect.bottom-destrect.top + srcrect.top;
  800. // Clip the source to the screen
  801. RECT srcrect2;
  802. if (!IntersectRect(&srcrect2, &srcrect, &m_fullscreen))
  803. return;
  804. // Correct the destination rectangle
  805. destrect.left += (srcrect2.left - srcrect.left);
  806. destrect.top += (srcrect2.top - srcrect.top);
  807. destrect.right = srcrect2.right-srcrect2.left + destrect.left;
  808. destrect.bottom = srcrect2.bottom-srcrect2.top + destrect.top;
  809. // Is there an existing CopyRect rectangle?
  810. if (m_copyrect_set)
  811. {
  812. // Yes, so compare their areas!
  813. if (((destrect.right-destrect.left) * (destrect.bottom-destrect.top))
  814. < ((m_copyrect_rect.right-m_copyrect_rect.left) * (m_copyrect_rect.bottom-m_copyrect_rect.top)))
  815. return;
  816. }
  817. // Set the copyrect...
  818. m_copyrect_rect = destrect;
  819. m_copyrect_src.x = srcrect2.left;
  820. m_copyrect_src.y = srcrect2.top;
  821. m_copyrect_set = TRUE;
  822. }
  823. }
  824. void
  825. vncClient::UpdateClipText(LPSTR text)
  826. {
  827. // Lock out any update sends and send clip text to the client
  828. omni_mutex_lock l(m_regionLock);
  829. rfbServerCutTextMsg message;
  830. message.length = Swap32IfLE(strlen(text));
  831. if (!SendRFBMsg(rfbServerCutText, (BYTE *) &message, sizeof(message)))
  832. {
  833. Kill();
  834. return;
  835. }
  836. if (!m_socket->SendExact(text, strlen(text)))
  837. {
  838. Kill();
  839. return;
  840. }
  841. }
  842. void
  843. vncClient::UpdatePalette()
  844. {
  845. omni_mutex_lock l(m_regionLock);
  846. m_palettechanged = TRUE;
  847. }
  848. // Functions used to set and retrieve the client settings
  849. char*
  850. vncClient::GetClientName()
  851. {
  852. return m_socket->GetPeerName();
  853. }
  854. // Internal methods
  855. BOOL
  856. vncClient::SendRFBMsg(CARD8 type, BYTE *buffer, int buflen)
  857. {
  858. // Set the message type
  859. ((rfbServerToClientMsg *)buffer)->type = type;
  860. // Send the message
  861. if (!m_socket->SendExact((char *) buffer, buflen))
  862. {
  863. log.Print(LL_CONNERR, VNCLOG("failed to send RFB message to clientn"));
  864. Kill();
  865. return FALSE;
  866. }
  867. return TRUE;
  868. }
  869. // Check for each rect in the list, which rects actually need sending
  870. inline void
  871. vncClient::CheckRects(vncRegion &rgn, rectlist &rects)
  872. {
  873. rectlist::iterator i;
  874. for (i = rects.begin(); i != rects.end(); i++)
  875. {
  876. // Get the buffer to check for changes in the rect
  877. m_buffer->GetChangedRegion(rgn, *i);
  878. }
  879. }
  880. // For each rectangle in the list, just copy the foreground buffer to the background,
  881. // to avoid false updates in the future.
  882. inline void
  883. vncClient::ClearRects(vncRegion &rgn, rectlist &rects)
  884. {
  885. rectlist::iterator i;
  886. for (i = rects.begin(); i != rects.end(); i++)
  887. {
  888. m_buffer->Clear(*i);
  889. rgn.AddRect(*i);
  890. }
  891. }
  892. // Grab the given rectangles using the smallest no of bands possible
  893. inline void
  894. vncClient::GrabRegion(vncRegion &rgn)
  895. {
  896. rectlist::iterator i;
  897. rectlist rects;
  898. RECT grabRect;
  899. // Get the rectangles
  900. if (!rgn.Rectangles(rects))
  901. return;
  902. // Clear the DIB rectangle
  903. SetRectEmpty(&grabRect);
  904. // Sort the rectangles in order of height
  905. rects.sort();
  906. for (i = rects.begin(); i != rects.end(); i++)
  907. {
  908. RECT current = *i;
  909. // Check that this rectangle is part of this capture region
  910. if (current.top > grabRect.bottom)
  911. {
  912. // If the existing rect is non-null the capture it
  913. if (!IsRectEmpty(&grabRect))
  914. m_buffer->GrabRect(grabRect);
  915. grabRect = current;
  916. } else {
  917. // Enlarge the region to be captured
  918. UnionRect(&grabRect, &current, &grabRect);
  919. }
  920. }
  921. // If there are still some rects to be done then do them
  922. if (!IsRectEmpty(&grabRect))
  923. m_buffer->GrabRect(grabRect);
  924. }
  925. BOOL
  926. vncClient::SendUpdate()
  927. {
  928. vncRegion toBeSent; // Region to actually be sent
  929. rectlist toBeSentList; // List of rectangles to actually send
  930. vncRegion toBeDone; // Region to check
  931. // If there is nothing to send then exit
  932. if (m_changed_rgn.IsEmpty() &&
  933. m_full_rgn.IsEmpty() &&
  934. !m_copyrect_set)
  935. return FALSE;
  936. // Check that the copyrect region doesn't intersect the full update region
  937. if (!m_full_rgn.IsEmpty() && m_copyrect_set)
  938. { vncRegion temp;
  939. temp.AddRect(m_copyrect_rect);
  940. temp.Intersect(m_full_rgn);
  941. if (!temp.IsEmpty())
  942. {
  943. m_changed_rgn.AddRect(m_copyrect_rect);
  944. m_copyrect_set = FALSE;
  945. }
  946. }
  947. // Handle the CopyRect region, if any
  948. if (m_copyrect_set)
  949. m_buffer->CopyRect(m_copyrect_rect, m_copyrect_src);
  950. // *** Currently, we only check for changes when there isn't a CopyRect to do
  951. if (!m_copyrect_set)
  952. {
  953. // GRAB THE SCREEN DATA
  954. // Get the region to be scanned and potentially sent
  955. toBeDone.Clear();
  956. toBeDone.Combine(m_incr_rgn);
  957. toBeDone.Subtract(m_full_rgn);
  958. toBeDone.Intersect(m_changed_rgn);
  959. // Get the region to grab
  960. vncRegion toBeGrabbed;
  961. toBeGrabbed.Clear();
  962. toBeGrabbed.Combine(m_full_rgn);
  963. toBeGrabbed.Combine(toBeDone);
  964. GrabRegion(toBeGrabbed);
  965. // CLEAR REGIONS THAT WON'T BE SCANNED
  966. // Get the region to definitely be sent
  967. toBeSent.Clear();
  968. if (!m_full_rgn.IsEmpty())
  969. {
  970. rectlist rectsToClear;
  971. // Retrieve and clear the rectangles
  972. if (m_full_rgn.Rectangles(rectsToClear))
  973. ClearRects(toBeSent, rectsToClear);
  974. }
  975. // SCAN INCREMENTAL REGIONS FOR CHANGES
  976. if (!toBeDone.IsEmpty())
  977. {
  978. rectlist rectsToScan;
  979. // Retrieve and scan the rectangles
  980. if (toBeDone.Rectangles(rectsToScan))
  981. CheckRects(toBeSent, rectsToScan);
  982. }
  983. // CLEAN UP THE MAIN REGIONS
  984. // Clear the bits we're about to deal with from the changed region
  985. m_changed_rgn.Subtract(m_incr_rgn);
  986. m_changed_rgn.Subtract(m_full_rgn);
  987. // Clear the full & incremental regions, since we've dealt with them
  988. if (!toBeSent.IsEmpty())
  989. {
  990. m_full_rgn.Clear();
  991. m_incr_rgn.Clear();
  992. }
  993. // Draw the mouse pointer at the appropriate position if necessary
  994. if (m_mousemoved)
  995. {
  996. // Grab the mouse
  997. m_oldmousepos = m_buffer->GrabMouse();
  998. if (IntersectRect(&m_oldmousepos, &m_oldmousepos, &m_fullscreen))
  999. m_buffer->GetChangedRegion(toBeSent, m_oldmousepos);
  1000. m_mousemoved = FALSE;
  1001. }
  1002. }
  1003. // Get the list of changed rectangles!
  1004. int numrects = 0;
  1005. if (toBeSent.Rectangles(toBeSentList))
  1006. {
  1007. // Find out how many rectangles this update will contain
  1008. rectlist::iterator i;
  1009. for (i=toBeSentList.begin(); i != toBeSentList.end(); i++)
  1010. {
  1011. numrects += m_buffer->GetNumCodedRects(*i);
  1012. }
  1013. }
  1014. // Handle the copyrect region
  1015. if (m_copyrect_set)
  1016. numrects++;
  1017. // If there are no rectangles then return
  1018. if (numrects == 0)
  1019. return FALSE;
  1020. // Otherwise, send <number of rectangles> header
  1021. rfbFramebufferUpdateMsg header;
  1022. header.nRects = Swap16IfLE(numrects);
  1023. if (!SendRFBMsg(rfbFramebufferUpdate, (BYTE *) &header, sz_rfbFramebufferUpdateMsg))
  1024. return TRUE;
  1025. // Encode & send the copyrect
  1026. if (m_copyrect_set)
  1027. {
  1028. m_copyrect_set = FALSE;
  1029. if(!SendCopyRect(m_copyrect_rect, m_copyrect_src))
  1030. return TRUE;
  1031. }
  1032. // Encode & send the actual rectangles
  1033. if (!SendRectangles(toBeSentList))
  1034. return TRUE;
  1035. // Both lists should be empty when we exit
  1036. _ASSERT(toBeSentList.empty());
  1037. return TRUE;
  1038. }
  1039. // Send a set of rectangles
  1040. BOOL
  1041. vncClient::SendRectangles(rectlist &rects)
  1042. {
  1043. RECT rect;
  1044. // Work through the list of rectangles, sending each one
  1045. while(!rects.empty())
  1046. {
  1047. rect = rects.front();
  1048. if (!SendRectangle(rect))
  1049. return FALSE;
  1050. rects.pop_front();
  1051. }
  1052. rects.clear();
  1053. return TRUE;
  1054. }
  1055. // Tell the encoder to send a single rectangle
  1056. BOOL
  1057. vncClient::SendRectangle(RECT &rect)
  1058. {
  1059. // Get the buffer to encode the rectangle
  1060. UINT bytes = m_buffer->TranslateRect(rect);
  1061. // Send the encoded data
  1062. return m_socket->SendExact((char *)(m_buffer->GetClientBuffer()), bytes);
  1063. }
  1064. // Send a single CopyRect message
  1065. BOOL
  1066. vncClient::SendCopyRect(RECT &dest, POINT &source)
  1067. {
  1068. // Create the message header
  1069. rfbFramebufferUpdateRectHeader copyrecthdr;
  1070. copyrecthdr.r.x = Swap16IfLE(dest.left);
  1071. copyrecthdr.r.y = Swap16IfLE(dest.top);
  1072. copyrecthdr.r.w = Swap16IfLE(dest.right-dest.left);
  1073. copyrecthdr.r.h = Swap16IfLE(dest.bottom-dest.top);
  1074. copyrecthdr.encoding = Swap32IfLE(rfbEncodingCopyRect);
  1075. // Create the CopyRect-specific section
  1076. rfbCopyRect copyrectbody;
  1077. copyrectbody.srcX = Swap16IfLE(source.x);
  1078. copyrectbody.srcY = Swap16IfLE(source.y);
  1079. // Now send the message;
  1080. if (!m_socket->SendExact((char *)&copyrecthdr, sizeof(copyrecthdr)))
  1081. return FALSE;
  1082. if (!m_socket->SendExact((char *)&copyrectbody, sizeof(copyrectbody)))
  1083. return FALSE;
  1084. return TRUE;
  1085. }
  1086. // Send the encoder-generated palette to the client
  1087. // This function only returns FALSE if the SendExact fails - any other
  1088. // error is coped with internally...
  1089. BOOL
  1090. vncClient::SendPalette()
  1091. {
  1092. rfbSetColourMapEntriesMsg setcmap;
  1093. RGBQUAD *rgbquad;
  1094. UINT ncolours = 256;
  1095. // Reserve space for the colour data
  1096. rgbquad = new RGBQUAD[ncolours];
  1097. if (rgbquad == NULL)
  1098. return TRUE;
  1099. // Get the data
  1100. if (!m_buffer->GetRemotePalette(rgbquad, ncolours))
  1101. {
  1102. delete [] rgbquad;
  1103. return TRUE;
  1104. }
  1105. // Compose the message
  1106. setcmap.type = rfbSetColourMapEntries;
  1107. setcmap.firstColour = Swap16IfLE(0);
  1108. setcmap.nColours = Swap16IfLE(ncolours);
  1109. if (!m_socket->SendExact((char *) &setcmap, sz_rfbSetColourMapEntriesMsg))
  1110. {
  1111. delete [] rgbquad;
  1112. return FALSE;
  1113. }
  1114. // Now send the actual colour data...
  1115. for (int i=0; i<ncolours; i++)
  1116. {
  1117. struct _PIXELDATA {
  1118. CARD16 r, g, b;
  1119. } pixeldata;
  1120. pixeldata.r = Swap16IfLE(((CARD16)rgbquad[i].rgbRed) << 8);
  1121. pixeldata.g = Swap16IfLE(((CARD16)rgbquad[i].rgbGreen) << 8);
  1122. pixeldata.b = Swap16IfLE(((CARD16)rgbquad[i].rgbBlue) << 8);
  1123. if (!m_socket->SendExact((char *) &pixeldata, sizeof(pixeldata)))
  1124. {
  1125. delete [] rgbquad;
  1126. return FALSE;
  1127. }
  1128. }
  1129. // Delete the rgbquad data
  1130. delete [] rgbquad;
  1131. return TRUE;
  1132. }