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

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