Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

CConnection.cxx 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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/Security.h>
  28. #include <rfb/SecurityClient.h>
  29. #include <rfb/CConnection.h>
  30. #include <rfb/util.h>
  31. #include <rfb/LogWriter.h>
  32. #include <rdr/InStream.h>
  33. #include <rdr/OutStream.h>
  34. using namespace rfb;
  35. static LogWriter vlog("CConnection");
  36. CConnection::CConnection()
  37. : csecurity(0), is(0), os(0), reader_(0), writer_(0),
  38. shared(false),
  39. state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
  40. framebuffer(NULL), decoder(this)
  41. {
  42. }
  43. CConnection::~CConnection()
  44. {
  45. setFramebuffer(NULL);
  46. if (csecurity)
  47. delete csecurity;
  48. delete reader_;
  49. reader_ = 0;
  50. delete writer_;
  51. writer_ = 0;
  52. }
  53. void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
  54. {
  55. is = is_;
  56. os = os_;
  57. }
  58. void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
  59. {
  60. decoder.flush();
  61. if ((framebuffer != NULL) && (fb != NULL)) {
  62. Rect rect;
  63. const rdr::U8* data;
  64. int stride;
  65. const rdr::U8 black[4] = { 0, 0, 0, 0 };
  66. // Copy still valid area
  67. rect.setXYWH(0, 0,
  68. __rfbmin(fb->width(), framebuffer->width()),
  69. __rfbmin(fb->height(), framebuffer->height()));
  70. data = framebuffer->getBuffer(framebuffer->getRect(), &stride);
  71. fb->imageRect(rect, data, stride);
  72. // Black out any new areas
  73. if (fb->width() > framebuffer->width()) {
  74. rect.setXYWH(framebuffer->width(), 0,
  75. fb->width() - framebuffer->width(),
  76. fb->height());
  77. fb->fillRect(rect, black);
  78. }
  79. if (fb->height() > framebuffer->height()) {
  80. rect.setXYWH(0, framebuffer->height(),
  81. fb->width(),
  82. fb->height() - framebuffer->height());
  83. fb->fillRect(rect, black);
  84. }
  85. }
  86. delete framebuffer;
  87. framebuffer = fb;
  88. }
  89. void CConnection::initialiseProtocol()
  90. {
  91. state_ = RFBSTATE_PROTOCOL_VERSION;
  92. }
  93. void CConnection::processMsg()
  94. {
  95. switch (state_) {
  96. case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
  97. case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break;
  98. case RFBSTATE_SECURITY: processSecurityMsg(); break;
  99. case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break;
  100. case RFBSTATE_INITIALISATION: processInitMsg(); break;
  101. case RFBSTATE_NORMAL: reader_->readMsg(); break;
  102. case RFBSTATE_UNINITIALISED:
  103. throw Exception("CConnection::processMsg: not initialised yet?");
  104. default:
  105. throw Exception("CConnection::processMsg: invalid state");
  106. }
  107. }
  108. void CConnection::processVersionMsg()
  109. {
  110. char verStr[13];
  111. int majorVersion;
  112. int minorVersion;
  113. vlog.debug("reading protocol version");
  114. if (!is->checkNoWait(12))
  115. return;
  116. is->readBytes(verStr, 12);
  117. verStr[12] = '\0';
  118. if (sscanf(verStr, "RFB %03d.%03d\n",
  119. &majorVersion, &minorVersion) != 2) {
  120. state_ = RFBSTATE_INVALID;
  121. throw Exception("reading version failed: not an RFB server?");
  122. }
  123. server.setVersion(majorVersion, minorVersion);
  124. vlog.info("Server supports RFB protocol version %d.%d",
  125. server.majorVersion, server.minorVersion);
  126. // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
  127. if (server.beforeVersion(3,3)) {
  128. vlog.error("Server gave unsupported RFB protocol version %d.%d",
  129. server.majorVersion, server.minorVersion);
  130. state_ = RFBSTATE_INVALID;
  131. throw Exception("Server gave unsupported RFB protocol version %d.%d",
  132. server.majorVersion, server.minorVersion);
  133. } else if (useProtocol3_3 || server.beforeVersion(3,7)) {
  134. server.setVersion(3,3);
  135. } else if (server.afterVersion(3,8)) {
  136. server.setVersion(3,8);
  137. }
  138. sprintf(verStr, "RFB %03d.%03d\n",
  139. server.majorVersion, server.minorVersion);
  140. os->writeBytes(verStr, 12);
  141. os->flush();
  142. state_ = RFBSTATE_SECURITY_TYPES;
  143. vlog.info("Using RFB protocol version %d.%d",
  144. server.majorVersion, server.minorVersion);
  145. }
  146. void CConnection::processSecurityTypesMsg()
  147. {
  148. vlog.debug("processing security types message");
  149. int secType = secTypeInvalid;
  150. std::list<rdr::U8> secTypes;
  151. secTypes = security.GetEnabledSecTypes();
  152. if (server.isVersion(3,3)) {
  153. // legacy 3.3 server may only offer "vnc authentication" or "none"
  154. secType = is->readU32();
  155. if (secType == secTypeInvalid) {
  156. throwConnFailedException();
  157. } else if (secType == secTypeNone || secType == secTypeVncAuth) {
  158. std::list<rdr::U8>::iterator i;
  159. for (i = secTypes.begin(); i != secTypes.end(); i++)
  160. if (*i == secType) {
  161. secType = *i;
  162. break;
  163. }
  164. if (i == secTypes.end())
  165. secType = secTypeInvalid;
  166. } else {
  167. vlog.error("Unknown 3.3 security type %d", secType);
  168. throw Exception("Unknown 3.3 security type");
  169. }
  170. } else {
  171. // >=3.7 server will offer us a list
  172. int nServerSecTypes = is->readU8();
  173. if (nServerSecTypes == 0)
  174. throwConnFailedException();
  175. std::list<rdr::U8>::iterator j;
  176. for (int i = 0; i < nServerSecTypes; i++) {
  177. rdr::U8 serverSecType = is->readU8();
  178. vlog.debug("Server offers security type %s(%d)",
  179. secTypeName(serverSecType), serverSecType);
  180. /*
  181. * Use the first type sent by server which matches client's type.
  182. * It means server's order specifies priority.
  183. */
  184. if (secType == secTypeInvalid) {
  185. for (j = secTypes.begin(); j != secTypes.end(); j++)
  186. if (*j == serverSecType) {
  187. secType = *j;
  188. break;
  189. }
  190. }
  191. }
  192. // Inform the server of our decision
  193. if (secType != secTypeInvalid) {
  194. os->writeU8(secType);
  195. os->flush();
  196. vlog.info("Choosing security type %s(%d)",secTypeName(secType),secType);
  197. }
  198. }
  199. if (secType == secTypeInvalid) {
  200. state_ = RFBSTATE_INVALID;
  201. vlog.error("No matching security types");
  202. throw Exception("No matching security types");
  203. }
  204. state_ = RFBSTATE_SECURITY;
  205. csecurity = security.GetCSecurity(this, secType);
  206. processSecurityMsg();
  207. }
  208. void CConnection::processSecurityMsg()
  209. {
  210. vlog.debug("processing security message");
  211. if (csecurity->processMsg()) {
  212. state_ = RFBSTATE_SECURITY_RESULT;
  213. processSecurityResultMsg();
  214. }
  215. }
  216. void CConnection::processSecurityResultMsg()
  217. {
  218. vlog.debug("processing security result message");
  219. int result;
  220. if (server.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
  221. result = secResultOK;
  222. } else {
  223. if (!is->checkNoWait(1)) return;
  224. result = is->readU32();
  225. }
  226. switch (result) {
  227. case secResultOK:
  228. securityCompleted();
  229. return;
  230. case secResultFailed:
  231. vlog.debug("auth failed");
  232. break;
  233. case secResultTooMany:
  234. vlog.debug("auth failed - too many tries");
  235. break;
  236. default:
  237. throw Exception("Unknown security result from server");
  238. }
  239. state_ = RFBSTATE_INVALID;
  240. if (server.beforeVersion(3,8))
  241. throw AuthFailureException();
  242. CharArray reason(is->readString());
  243. throw AuthFailureException(reason.buf);
  244. }
  245. void CConnection::processInitMsg()
  246. {
  247. vlog.debug("reading server initialisation");
  248. reader_->readServerInit();
  249. }
  250. void CConnection::throwConnFailedException()
  251. {
  252. state_ = RFBSTATE_INVALID;
  253. CharArray reason;
  254. reason.buf = is->readString();
  255. throw ConnFailedException(reason.buf);
  256. }
  257. void CConnection::securityCompleted()
  258. {
  259. state_ = RFBSTATE_INITIALISATION;
  260. reader_ = new CMsgReader(this, is);
  261. writer_ = new CMsgWriter(&server, os);
  262. vlog.debug("Authentication success!");
  263. authSuccess();
  264. writer_->writeClientInit(shared);
  265. }
  266. void CConnection::setDesktopSize(int w, int h)
  267. {
  268. decoder.flush();
  269. CMsgHandler::setDesktopSize(w,h);
  270. }
  271. void CConnection::setExtendedDesktopSize(unsigned reason,
  272. unsigned result,
  273. int w, int h,
  274. const ScreenSet& layout)
  275. {
  276. decoder.flush();
  277. CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
  278. }
  279. void CConnection::serverInit(int width, int height,
  280. const PixelFormat& pf,
  281. const char* name)
  282. {
  283. CMsgHandler::serverInit(width, height, pf, name);
  284. state_ = RFBSTATE_NORMAL;
  285. vlog.debug("initialisation done");
  286. initDone();
  287. assert(framebuffer != NULL);
  288. assert(framebuffer->width() == server.width());
  289. assert(framebuffer->height() == server.height());
  290. }
  291. void CConnection::readAndDecodeRect(const Rect& r, int encoding,
  292. ModifiablePixelBuffer* pb)
  293. {
  294. decoder.decodeRect(r, encoding, pb);
  295. decoder.flush();
  296. }
  297. void CConnection::framebufferUpdateStart()
  298. {
  299. CMsgHandler::framebufferUpdateStart();
  300. }
  301. void CConnection::framebufferUpdateEnd()
  302. {
  303. decoder.flush();
  304. CMsgHandler::framebufferUpdateEnd();
  305. }
  306. void CConnection::dataRect(const Rect& r, int encoding)
  307. {
  308. decoder.decodeRect(r, encoding, framebuffer);
  309. }
  310. void CConnection::authSuccess()
  311. {
  312. }
  313. void CConnection::initDone()
  314. {
  315. }
  316. void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
  317. {
  318. CMsgHandler::fence(flags, len, data);
  319. if (!(flags & fenceFlagRequest))
  320. return;
  321. // We cannot guarantee any synchronisation at this level
  322. flags = 0;
  323. writer()->writeFence(flags, len, data);
  324. }