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.

SMsgReader.cxx 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2009-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 <stdio.h>
  20. #include <rdr/InStream.h>
  21. #include <rdr/ZlibInStream.h>
  22. #include <rfb/msgTypes.h>
  23. #include <rfb/qemuTypes.h>
  24. #include <rfb/clipboardTypes.h>
  25. #include <rfb/Exception.h>
  26. #include <rfb/util.h>
  27. #include <rfb/SMsgHandler.h>
  28. #include <rfb/SMsgReader.h>
  29. #include <rfb/Configuration.h>
  30. #include <rfb/LogWriter.h>
  31. using namespace rfb;
  32. static LogWriter vlog("SMsgReader");
  33. static IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024);
  34. SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_)
  35. : handler(handler_), is(is_)
  36. {
  37. }
  38. SMsgReader::~SMsgReader()
  39. {
  40. }
  41. void SMsgReader::readClientInit()
  42. {
  43. bool shared = is->readU8();
  44. handler->clientInit(shared);
  45. }
  46. void SMsgReader::readMsg()
  47. {
  48. int msgType = is->readU8();
  49. switch (msgType) {
  50. case msgTypeSetPixelFormat:
  51. readSetPixelFormat();
  52. break;
  53. case msgTypeSetEncodings:
  54. readSetEncodings();
  55. break;
  56. case msgTypeSetDesktopSize:
  57. readSetDesktopSize();
  58. break;
  59. case msgTypeFramebufferUpdateRequest:
  60. readFramebufferUpdateRequest();
  61. break;
  62. case msgTypeEnableContinuousUpdates:
  63. readEnableContinuousUpdates();
  64. break;
  65. case msgTypeClientFence:
  66. readFence();
  67. break;
  68. case msgTypeKeyEvent:
  69. readKeyEvent();
  70. break;
  71. case msgTypePointerEvent:
  72. readPointerEvent();
  73. break;
  74. case msgTypeClientCutText:
  75. readClientCutText();
  76. break;
  77. case msgTypeQEMUClientMessage:
  78. readQEMUMessage();
  79. break;
  80. default:
  81. vlog.error("unknown message type %d", msgType);
  82. throw Exception("unknown message type");
  83. }
  84. }
  85. void SMsgReader::readSetPixelFormat()
  86. {
  87. is->skip(3);
  88. PixelFormat pf;
  89. pf.read(is);
  90. handler->setPixelFormat(pf);
  91. }
  92. void SMsgReader::readSetEncodings()
  93. {
  94. is->skip(1);
  95. int nEncodings = is->readU16();
  96. rdr::S32Array encodings(nEncodings);
  97. for (int i = 0; i < nEncodings; i++)
  98. encodings.buf[i] = is->readU32();
  99. handler->setEncodings(nEncodings, encodings.buf);
  100. }
  101. void SMsgReader::readSetDesktopSize()
  102. {
  103. int width, height;
  104. int screens, i;
  105. rdr::U32 id, flags;
  106. int sx, sy, sw, sh;
  107. ScreenSet layout;
  108. is->skip(1);
  109. width = is->readU16();
  110. height = is->readU16();
  111. screens = is->readU8();
  112. is->skip(1);
  113. for (i = 0;i < screens;i++) {
  114. id = is->readU32();
  115. sx = is->readU16();
  116. sy = is->readU16();
  117. sw = is->readU16();
  118. sh = is->readU16();
  119. flags = is->readU32();
  120. layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
  121. }
  122. handler->setDesktopSize(width, height, layout);
  123. }
  124. void SMsgReader::readFramebufferUpdateRequest()
  125. {
  126. bool inc = is->readU8();
  127. int x = is->readU16();
  128. int y = is->readU16();
  129. int w = is->readU16();
  130. int h = is->readU16();
  131. handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc);
  132. }
  133. void SMsgReader::readEnableContinuousUpdates()
  134. {
  135. bool enable;
  136. int x, y, w, h;
  137. enable = is->readU8();
  138. x = is->readU16();
  139. y = is->readU16();
  140. w = is->readU16();
  141. h = is->readU16();
  142. handler->enableContinuousUpdates(enable, x, y, w, h);
  143. }
  144. void SMsgReader::readFence()
  145. {
  146. rdr::U32 flags;
  147. rdr::U8 len;
  148. char data[64];
  149. is->skip(3);
  150. flags = is->readU32();
  151. len = is->readU8();
  152. if (len > sizeof(data)) {
  153. vlog.error("Ignoring fence with too large payload");
  154. is->skip(len);
  155. return;
  156. }
  157. is->readBytes(data, len);
  158. handler->fence(flags, len, data);
  159. }
  160. void SMsgReader::readKeyEvent()
  161. {
  162. bool down = is->readU8();
  163. is->skip(2);
  164. rdr::U32 key = is->readU32();
  165. handler->keyEvent(key, 0, down);
  166. }
  167. void SMsgReader::readPointerEvent()
  168. {
  169. int mask = is->readU8();
  170. int x = is->readU16();
  171. int y = is->readU16();
  172. handler->pointerEvent(Point(x, y), mask);
  173. }
  174. void SMsgReader::readClientCutText()
  175. {
  176. is->skip(3);
  177. rdr::U32 len = is->readU32();
  178. if (len & 0x80000000) {
  179. rdr::S32 slen = len;
  180. slen = -slen;
  181. readExtendedClipboard(slen);
  182. return;
  183. }
  184. if (len > (size_t)maxCutText) {
  185. is->skip(len);
  186. vlog.error("Cut text too long (%d bytes) - ignoring", len);
  187. return;
  188. }
  189. CharArray ca(len);
  190. is->readBytes(ca.buf, len);
  191. CharArray filtered(convertLF(ca.buf, len));
  192. handler->clientCutText(filtered.buf);
  193. }
  194. void SMsgReader::readExtendedClipboard(rdr::S32 len)
  195. {
  196. rdr::U32 flags;
  197. rdr::U32 action;
  198. if (len < 4)
  199. throw Exception("Invalid extended clipboard message");
  200. if (len > maxCutText) {
  201. vlog.error("Extended clipboard message too long (%d bytes) - ignoring", len);
  202. is->skip(len);
  203. return;
  204. }
  205. flags = is->readU32();
  206. action = flags & clipboardActionMask;
  207. if (action & clipboardCaps) {
  208. int i;
  209. size_t num;
  210. rdr::U32 lengths[16];
  211. num = 0;
  212. for (i = 0;i < 16;i++) {
  213. if (flags & (1 << i))
  214. num++;
  215. }
  216. if (len < (rdr::S32)(4 + 4*num))
  217. throw Exception("Invalid extended clipboard message");
  218. num = 0;
  219. for (i = 0;i < 16;i++) {
  220. if (flags & (1 << i))
  221. lengths[num++] = is->readU32();
  222. }
  223. handler->handleClipboardCaps(flags, lengths);
  224. } else if (action == clipboardProvide) {
  225. rdr::ZlibInStream zis;
  226. int i;
  227. size_t num;
  228. size_t lengths[16];
  229. rdr::U8* buffers[16];
  230. zis.setUnderlying(is, len - 4);
  231. num = 0;
  232. for (i = 0;i < 16;i++) {
  233. if (!(flags & 1 << i))
  234. continue;
  235. lengths[num] = zis.readU32();
  236. if (lengths[num] > (size_t)maxCutText) {
  237. vlog.error("Extended clipboard data too long (%d bytes) - ignoring",
  238. (unsigned)lengths[num]);
  239. zis.skip(lengths[num]);
  240. flags &= ~(1 << i);
  241. continue;
  242. }
  243. buffers[num] = new rdr::U8[lengths[num]];
  244. zis.readBytes(buffers[num], lengths[num]);
  245. num++;
  246. }
  247. zis.removeUnderlying();
  248. handler->handleClipboardProvide(flags, lengths, buffers);
  249. num = 0;
  250. for (i = 0;i < 16;i++) {
  251. if (!(flags & 1 << i))
  252. continue;
  253. delete [] buffers[num++];
  254. }
  255. } else {
  256. switch (action) {
  257. case clipboardRequest:
  258. handler->handleClipboardRequest(flags);
  259. break;
  260. case clipboardPeek:
  261. handler->handleClipboardPeek(flags);
  262. break;
  263. case clipboardNotify:
  264. handler->handleClipboardNotify(flags);
  265. break;
  266. default:
  267. throw Exception("Invalid extended clipboard action");
  268. }
  269. }
  270. }
  271. void SMsgReader::readQEMUMessage()
  272. {
  273. int subType = is->readU8();
  274. switch (subType) {
  275. case qemuExtendedKeyEvent:
  276. readQEMUKeyEvent();
  277. break;
  278. default:
  279. throw Exception("unknown QEMU submessage type %d", subType);
  280. }
  281. }
  282. void SMsgReader::readQEMUKeyEvent()
  283. {
  284. bool down = is->readU16();
  285. rdr::U32 keysym = is->readU32();
  286. rdr::U32 keycode = is->readU32();
  287. if (!keycode) {
  288. vlog.error("Key event without keycode - ignoring");
  289. return;
  290. }
  291. handler->keyEvent(keysym, keycode, down);
  292. }