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 16KB

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