You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CConnection.cxx 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2011-2019 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #include <assert.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <rfb/Exception.h>
  23. #include <rfb/fenceTypes.h>
  24. #include <rfb/CMsgReader.h>
  25. #include <rfb/CMsgWriter.h>
  26. #include <rfb/CSecurity.h>
  27. #include <rfb/Decoder.h>
  28. #include <rfb/Security.h>
  29. #include <rfb/SecurityClient.h>
  30. #include <rfb/CConnection.h>
  31. #include <rfb/util.h>
  32. #include <rfb/LogWriter.h>
  33. #include <rdr/InStream.h>
  34. #include <rdr/OutStream.h>
  35. using namespace rfb;
  36. static LogWriter vlog("CConnection");
  37. CConnection::CConnection()
  38. : csecurity(0),
  39. supportsLocalCursor(false), supportsDesktopResize(false),
  40. supportsLEDState(false),
  41. is(0), os(0), reader_(0), writer_(0),
  42. shared(false),
  43. state_(RFBSTATE_UNINITIALISED),
  44. pendingPFChange(false), preferredEncoding(encodingTight),
  45. compressLevel(2), qualityLevel(-1),
  46. formatChange(false), encodingChange(false),
  47. firstUpdate(true), pendingUpdate(false), continuousUpdates(false),
  48. forceNonincremental(true),
  49. framebuffer(NULL), decoder(this),
  50. serverClipboard(NULL)
  51. {
  52. }
  53. CConnection::~CConnection()
  54. {
  55. setFramebuffer(NULL);
  56. if (csecurity)
  57. delete csecurity;
  58. delete reader_;
  59. reader_ = 0;
  60. delete writer_;
  61. writer_ = 0;
  62. strFree(serverClipboard);
  63. }
  64. void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
  65. {
  66. is = is_;
  67. os = os_;
  68. }
  69. void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
  70. {
  71. decoder.flush();
  72. if (fb) {
  73. assert(fb->width() == server.width());
  74. assert(fb->height() == server.height());
  75. }
  76. if ((framebuffer != NULL) && (fb != NULL)) {
  77. Rect rect;
  78. const rdr::U8* data;
  79. int stride;
  80. const rdr::U8 black[4] = { 0, 0, 0, 0 };
  81. // Copy still valid area
  82. rect.setXYWH(0, 0,
  83. __rfbmin(fb->width(), framebuffer->width()),
  84. __rfbmin(fb->height(), framebuffer->height()));
  85. data = framebuffer->getBuffer(framebuffer->getRect(), &stride);
  86. fb->imageRect(rect, data, stride);
  87. // Black out any new areas
  88. if (fb->width() > framebuffer->width()) {
  89. rect.setXYWH(framebuffer->width(), 0,
  90. fb->width() - framebuffer->width(),
  91. fb->height());
  92. fb->fillRect(rect, black);
  93. }
  94. if (fb->height() > framebuffer->height()) {
  95. rect.setXYWH(0, framebuffer->height(),
  96. fb->width(),
  97. fb->height() - framebuffer->height());
  98. fb->fillRect(rect, black);
  99. }
  100. }
  101. delete framebuffer;
  102. framebuffer = fb;
  103. }
  104. void CConnection::initialiseProtocol()
  105. {
  106. state_ = RFBSTATE_PROTOCOL_VERSION;
  107. }
  108. void CConnection::processMsg()
  109. {
  110. switch (state_) {
  111. case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
  112. case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break;
  113. case RFBSTATE_SECURITY: processSecurityMsg(); break;
  114. case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break;
  115. case RFBSTATE_INITIALISATION: processInitMsg(); break;
  116. case RFBSTATE_NORMAL: reader_->readMsg(); break;
  117. case RFBSTATE_UNINITIALISED:
  118. throw Exception("CConnection::processMsg: not initialised yet?");
  119. default:
  120. throw Exception("CConnection::processMsg: invalid state");
  121. }
  122. }
  123. void CConnection::processVersionMsg()
  124. {
  125. char verStr[27]; // FIXME: gcc has some bug in format-overflow
  126. int majorVersion;
  127. int minorVersion;
  128. vlog.debug("reading protocol version");
  129. if (!is->checkNoWait(12))
  130. return;
  131. is->readBytes(verStr, 12);
  132. verStr[12] = '\0';
  133. if (sscanf(verStr, "RFB %03d.%03d\n",
  134. &majorVersion, &minorVersion) != 2) {
  135. state_ = RFBSTATE_INVALID;
  136. throw Exception("reading version failed: not an RFB server?");
  137. }
  138. server.setVersion(majorVersion, minorVersion);
  139. vlog.info("Server supports RFB protocol version %d.%d",
  140. server.majorVersion, server.minorVersion);
  141. // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
  142. if (server.beforeVersion(3,3)) {
  143. vlog.error("Server gave unsupported RFB protocol version %d.%d",
  144. server.majorVersion, server.minorVersion);
  145. state_ = RFBSTATE_INVALID;
  146. throw Exception("Server gave unsupported RFB protocol version %d.%d",
  147. server.majorVersion, server.minorVersion);
  148. } else if (server.beforeVersion(3,7)) {
  149. server.setVersion(3,3);
  150. } else if (server.afterVersion(3,8)) {
  151. server.setVersion(3,8);
  152. }
  153. sprintf(verStr, "RFB %03d.%03d\n",
  154. server.majorVersion, server.minorVersion);
  155. os->writeBytes(verStr, 12);
  156. os->flush();
  157. state_ = RFBSTATE_SECURITY_TYPES;
  158. vlog.info("Using RFB protocol version %d.%d",
  159. server.majorVersion, server.minorVersion);
  160. }
  161. void CConnection::processSecurityTypesMsg()
  162. {
  163. vlog.debug("processing security types message");
  164. int secType = secTypeInvalid;
  165. std::list<rdr::U8> secTypes;
  166. secTypes = security.GetEnabledSecTypes();
  167. if (server.isVersion(3,3)) {
  168. // legacy 3.3 server may only offer "vnc authentication" or "none"
  169. secType = is->readU32();
  170. if (secType == secTypeInvalid) {
  171. throwConnFailedException();
  172. } else if (secType == secTypeNone || secType == secTypeVncAuth) {
  173. std::list<rdr::U8>::iterator i;
  174. for (i = secTypes.begin(); i != secTypes.end(); i++)
  175. if (*i == secType) {
  176. secType = *i;
  177. break;
  178. }
  179. if (i == secTypes.end())
  180. secType = secTypeInvalid;
  181. } else {
  182. vlog.error("Unknown 3.3 security type %d", secType);
  183. throw Exception("Unknown 3.3 security type");
  184. }
  185. } else {
  186. // >=3.7 server will offer us a list
  187. int nServerSecTypes = is->readU8();
  188. if (nServerSecTypes == 0)
  189. throwConnFailedException();
  190. std::list<rdr::U8>::iterator j;
  191. for (int i = 0; i < nServerSecTypes; i++) {
  192. rdr::U8 serverSecType = is->readU8();
  193. vlog.debug("Server offers security type %s(%d)",
  194. secTypeName(serverSecType), serverSecType);
  195. /*
  196. * Use the first type sent by server which matches client's type.
  197. * It means server's order specifies priority.
  198. */
  199. if (secType == secTypeInvalid) {
  200. for (j = secTypes.begin(); j != secTypes.end(); j++)
  201. if (*j == serverSecType) {
  202. secType = *j;
  203. break;
  204. }
  205. }
  206. }
  207. // Inform the server of our decision
  208. if (secType != secTypeInvalid) {
  209. os->writeU8(secType);
  210. os->flush();
  211. vlog.info("Choosing security type %s(%d)",secTypeName(secType),secType);
  212. }
  213. }
  214. if (secType == secTypeInvalid) {
  215. state_ = RFBSTATE_INVALID;
  216. vlog.error("No matching security types");
  217. throw Exception("No matching security types");
  218. }
  219. state_ = RFBSTATE_SECURITY;
  220. csecurity = security.GetCSecurity(this, secType);
  221. processSecurityMsg();
  222. }
  223. void CConnection::processSecurityMsg()
  224. {
  225. vlog.debug("processing security message");
  226. if (csecurity->processMsg()) {
  227. state_ = RFBSTATE_SECURITY_RESULT;
  228. processSecurityResultMsg();
  229. }
  230. }
  231. void CConnection::processSecurityResultMsg()
  232. {
  233. vlog.debug("processing security result message");
  234. int result;
  235. if (server.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
  236. result = secResultOK;
  237. } else {
  238. if (!is->checkNoWait(1)) return;
  239. result = is->readU32();
  240. }
  241. switch (result) {
  242. case secResultOK:
  243. securityCompleted();
  244. return;
  245. case secResultFailed:
  246. vlog.debug("auth failed");
  247. break;
  248. case secResultTooMany:
  249. vlog.debug("auth failed - too many tries");
  250. break;
  251. default:
  252. throw Exception("Unknown security result from server");
  253. }
  254. state_ = RFBSTATE_INVALID;
  255. if (server.beforeVersion(3,8))
  256. throw AuthFailureException();
  257. CharArray reason(is->readString());
  258. throw AuthFailureException(reason.buf);
  259. }
  260. void CConnection::processInitMsg()
  261. {
  262. vlog.debug("reading server initialisation");
  263. reader_->readServerInit();
  264. }
  265. void CConnection::throwConnFailedException()
  266. {
  267. state_ = RFBSTATE_INVALID;
  268. CharArray reason;
  269. reason.buf = is->readString();
  270. throw ConnFailedException(reason.buf);
  271. }
  272. void CConnection::securityCompleted()
  273. {
  274. state_ = RFBSTATE_INITIALISATION;
  275. reader_ = new CMsgReader(this, is);
  276. writer_ = new CMsgWriter(&server, os);
  277. vlog.debug("Authentication success!");
  278. authSuccess();
  279. writer_->writeClientInit(shared);
  280. }
  281. void CConnection::setDesktopSize(int w, int h)
  282. {
  283. decoder.flush();
  284. CMsgHandler::setDesktopSize(w,h);
  285. if (continuousUpdates)
  286. writer()->writeEnableContinuousUpdates(true, 0, 0,
  287. server.width(),
  288. server.height());
  289. resizeFramebuffer();
  290. assert(framebuffer != NULL);
  291. assert(framebuffer->width() == server.width());
  292. assert(framebuffer->height() == server.height());
  293. }
  294. void CConnection::setExtendedDesktopSize(unsigned reason,
  295. unsigned result,
  296. int w, int h,
  297. const ScreenSet& layout)
  298. {
  299. decoder.flush();
  300. CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
  301. if (continuousUpdates)
  302. writer()->writeEnableContinuousUpdates(true, 0, 0,
  303. server.width(),
  304. server.height());
  305. resizeFramebuffer();
  306. assert(framebuffer != NULL);
  307. assert(framebuffer->width() == server.width());
  308. assert(framebuffer->height() == server.height());
  309. }
  310. void CConnection::endOfContinuousUpdates()
  311. {
  312. CMsgHandler::endOfContinuousUpdates();
  313. // We've gotten the marker for a format change, so make the pending
  314. // one active
  315. if (pendingPFChange) {
  316. server.setPF(pendingPF);
  317. pendingPFChange = false;
  318. // We might have another change pending
  319. if (formatChange)
  320. requestNewUpdate();
  321. }
  322. }
  323. void CConnection::serverInit(int width, int height,
  324. const PixelFormat& pf,
  325. const char* name)
  326. {
  327. CMsgHandler::serverInit(width, height, pf, name);
  328. state_ = RFBSTATE_NORMAL;
  329. vlog.debug("initialisation done");
  330. initDone();
  331. assert(framebuffer != NULL);
  332. assert(framebuffer->width() == server.width());
  333. assert(framebuffer->height() == server.height());
  334. // We want to make sure we call SetEncodings at least once
  335. encodingChange = true;
  336. requestNewUpdate();
  337. // This initial update request is a bit of a corner case, so we need
  338. // to help out setting the correct format here.
  339. if (pendingPFChange) {
  340. server.setPF(pendingPF);
  341. pendingPFChange = false;
  342. }
  343. }
  344. void CConnection::readAndDecodeRect(const Rect& r, int encoding,
  345. ModifiablePixelBuffer* pb)
  346. {
  347. decoder.decodeRect(r, encoding, pb);
  348. decoder.flush();
  349. }
  350. void CConnection::framebufferUpdateStart()
  351. {
  352. CMsgHandler::framebufferUpdateStart();
  353. assert(framebuffer != NULL);
  354. // Note: This might not be true if continuous updates are supported
  355. pendingUpdate = false;
  356. requestNewUpdate();
  357. }
  358. void CConnection::framebufferUpdateEnd()
  359. {
  360. decoder.flush();
  361. CMsgHandler::framebufferUpdateEnd();
  362. // A format change has been scheduled and we are now past the update
  363. // with the old format. Time to active the new one.
  364. if (pendingPFChange && !continuousUpdates) {
  365. server.setPF(pendingPF);
  366. pendingPFChange = false;
  367. }
  368. if (firstUpdate) {
  369. if (server.supportsContinuousUpdates) {
  370. vlog.info("Enabling continuous updates");
  371. continuousUpdates = true;
  372. writer()->writeEnableContinuousUpdates(true, 0, 0,
  373. server.width(),
  374. server.height());
  375. }
  376. firstUpdate = false;
  377. }
  378. }
  379. void CConnection::dataRect(const Rect& r, int encoding)
  380. {
  381. decoder.decodeRect(r, encoding, framebuffer);
  382. }
  383. void CConnection::serverCutText(const char* str)
  384. {
  385. strFree(serverClipboard);
  386. serverClipboard = NULL;
  387. serverClipboard = latin1ToUTF8(str);
  388. handleClipboardAnnounce(true);
  389. }
  390. void CConnection::authSuccess()
  391. {
  392. }
  393. void CConnection::initDone()
  394. {
  395. }
  396. void CConnection::resizeFramebuffer()
  397. {
  398. assert(false);
  399. }
  400. void CConnection::handleClipboardRequest()
  401. {
  402. }
  403. void CConnection::handleClipboardAnnounce(bool available)
  404. {
  405. }
  406. void CConnection::handleClipboardData(const char* data)
  407. {
  408. }
  409. void CConnection::requestClipboard()
  410. {
  411. if (serverClipboard != NULL) {
  412. handleClipboardData(serverClipboard);
  413. return;
  414. }
  415. }
  416. void CConnection::announceClipboard(bool available)
  417. {
  418. if (available)
  419. handleClipboardRequest();
  420. }
  421. void CConnection::sendClipboardData(const char* data)
  422. {
  423. CharArray latin1(utf8ToLatin1(data));
  424. writer()->writeClientCutText(latin1.buf);
  425. }
  426. void CConnection::refreshFramebuffer()
  427. {
  428. forceNonincremental = true;
  429. // Without continuous updates we have to make sure we only have a
  430. // single update in flight, so we'll have to wait to do the refresh
  431. if (continuousUpdates)
  432. requestNewUpdate();
  433. }
  434. void CConnection::setPreferredEncoding(int encoding)
  435. {
  436. if (preferredEncoding == encoding)
  437. return;
  438. preferredEncoding = encoding;
  439. encodingChange = true;
  440. }
  441. int CConnection::getPreferredEncoding()
  442. {
  443. return preferredEncoding;
  444. }
  445. void CConnection::setCompressLevel(int level)
  446. {
  447. if (compressLevel == level)
  448. return;
  449. compressLevel = level;
  450. encodingChange = true;
  451. }
  452. void CConnection::setQualityLevel(int level)
  453. {
  454. if (qualityLevel == level)
  455. return;
  456. qualityLevel = level;
  457. encodingChange = true;
  458. }
  459. void CConnection::setPF(const PixelFormat& pf)
  460. {
  461. if (server.pf().equal(pf) && !formatChange)
  462. return;
  463. nextPF = pf;
  464. formatChange = true;
  465. }
  466. void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
  467. {
  468. CMsgHandler::fence(flags, len, data);
  469. if (!(flags & fenceFlagRequest))
  470. return;
  471. // We cannot guarantee any synchronisation at this level
  472. flags = 0;
  473. writer()->writeFence(flags, len, data);
  474. }
  475. // requestNewUpdate() requests an update from the server, having set the
  476. // format and encoding appropriately.
  477. void CConnection::requestNewUpdate()
  478. {
  479. if (formatChange && !pendingPFChange) {
  480. /* Catch incorrect requestNewUpdate calls */
  481. assert(!pendingUpdate || continuousUpdates);
  482. // We have to make sure we switch the internal format at a safe
  483. // time. For continuous updates we temporarily disable updates and
  484. // look for a EndOfContinuousUpdates message to see when to switch.
  485. // For classical updates we just got a new update right before this
  486. // function was called, so we need to make sure we finish that
  487. // update before we can switch.
  488. pendingPFChange = true;
  489. pendingPF = nextPF;
  490. if (continuousUpdates)
  491. writer()->writeEnableContinuousUpdates(false, 0, 0, 0, 0);
  492. writer()->writeSetPixelFormat(pendingPF);
  493. if (continuousUpdates)
  494. writer()->writeEnableContinuousUpdates(true, 0, 0,
  495. server.width(),
  496. server.height());
  497. formatChange = false;
  498. }
  499. if (encodingChange) {
  500. updateEncodings();
  501. encodingChange = false;
  502. }
  503. if (forceNonincremental || !continuousUpdates) {
  504. pendingUpdate = true;
  505. writer()->writeFramebufferUpdateRequest(Rect(0, 0,
  506. server.width(),
  507. server.height()),
  508. !forceNonincremental);
  509. }
  510. forceNonincremental = false;
  511. }
  512. // Ask for encodings based on which decoders are supported. Assumes higher
  513. // encoding numbers are more desirable.
  514. void CConnection::updateEncodings()
  515. {
  516. std::list<rdr::U32> encodings;
  517. if (supportsLocalCursor) {
  518. encodings.push_back(pseudoEncodingCursorWithAlpha);
  519. encodings.push_back(pseudoEncodingVMwareCursor);
  520. encodings.push_back(pseudoEncodingCursor);
  521. encodings.push_back(pseudoEncodingXCursor);
  522. }
  523. if (supportsDesktopResize) {
  524. encodings.push_back(pseudoEncodingDesktopSize);
  525. encodings.push_back(pseudoEncodingExtendedDesktopSize);
  526. }
  527. if (supportsLEDState) {
  528. encodings.push_back(pseudoEncodingLEDState);
  529. encodings.push_back(pseudoEncodingVMwareLEDState);
  530. }
  531. encodings.push_back(pseudoEncodingDesktopName);
  532. encodings.push_back(pseudoEncodingLastRect);
  533. encodings.push_back(pseudoEncodingContinuousUpdates);
  534. encodings.push_back(pseudoEncodingFence);
  535. encodings.push_back(pseudoEncodingQEMUKeyEvent);
  536. if (Decoder::supported(preferredEncoding)) {
  537. encodings.push_back(preferredEncoding);
  538. }
  539. encodings.push_back(encodingCopyRect);
  540. for (int i = encodingMax; i >= 0; i--) {
  541. if ((i != preferredEncoding) && Decoder::supported(i))
  542. encodings.push_back(i);
  543. }
  544. if (compressLevel >= 0 && compressLevel <= 9)
  545. encodings.push_back(pseudoEncodingCompressLevel0 + compressLevel);
  546. if (qualityLevel >= 0 && qualityLevel <= 9)
  547. encodings.push_back(pseudoEncodingQualityLevel0 + qualityLevel);
  548. writer()->writeSetEncodings(encodings);
  549. }