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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2009-2014 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 <rfb/msgTypes.h>
  22. #include <rfb/qemuTypes.h>
  23. #include <rfb/Exception.h>
  24. #include <rfb/util.h>
  25. #include <rfb/SMsgHandler.h>
  26. #include <rfb/SMsgReader.h>
  27. #include <rfb/Configuration.h>
  28. #include <rfb/LogWriter.h>
  29. using namespace rfb;
  30. static LogWriter vlog("SMsgReader");
  31. static IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024);
  32. SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_)
  33. : handler(handler_), is(is_)
  34. {
  35. }
  36. SMsgReader::~SMsgReader()
  37. {
  38. }
  39. void SMsgReader::readClientInit()
  40. {
  41. bool shared = is->readU8();
  42. handler->clientInit(shared);
  43. }
  44. void SMsgReader::readMsg()
  45. {
  46. int msgType = is->readU8();
  47. switch (msgType) {
  48. case msgTypeSetPixelFormat:
  49. readSetPixelFormat();
  50. break;
  51. case msgTypeSetEncodings:
  52. readSetEncodings();
  53. break;
  54. case msgTypeSetDesktopSize:
  55. readSetDesktopSize();
  56. break;
  57. case msgTypeFramebufferUpdateRequest:
  58. readFramebufferUpdateRequest();
  59. break;
  60. case msgTypeEnableContinuousUpdates:
  61. readEnableContinuousUpdates();
  62. break;
  63. case msgTypeClientFence:
  64. readFence();
  65. break;
  66. case msgTypeKeyEvent:
  67. readKeyEvent();
  68. break;
  69. case msgTypePointerEvent:
  70. readPointerEvent();
  71. break;
  72. case msgTypeClientCutText:
  73. readClientCutText();
  74. break;
  75. case msgTypeQEMUClientMessage:
  76. readQEMUMessage();
  77. break;
  78. default:
  79. vlog.error("unknown message type %d", msgType);
  80. throw Exception("unknown message type");
  81. }
  82. }
  83. void SMsgReader::readSetPixelFormat()
  84. {
  85. is->skip(3);
  86. PixelFormat pf;
  87. pf.read(is);
  88. handler->setPixelFormat(pf);
  89. }
  90. void SMsgReader::readSetEncodings()
  91. {
  92. is->skip(1);
  93. int nEncodings = is->readU16();
  94. rdr::S32Array encodings(nEncodings);
  95. for (int i = 0; i < nEncodings; i++)
  96. encodings.buf[i] = is->readU32();
  97. handler->setEncodings(nEncodings, encodings.buf);
  98. }
  99. void SMsgReader::readSetDesktopSize()
  100. {
  101. int width, height;
  102. int screens, i;
  103. rdr::U32 id, flags;
  104. int sx, sy, sw, sh;
  105. ScreenSet layout;
  106. is->skip(1);
  107. width = is->readU16();
  108. height = is->readU16();
  109. screens = is->readU8();
  110. is->skip(1);
  111. for (i = 0;i < screens;i++) {
  112. id = is->readU32();
  113. sx = is->readU16();
  114. sy = is->readU16();
  115. sw = is->readU16();
  116. sh = is->readU16();
  117. flags = is->readU32();
  118. layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
  119. }
  120. handler->setDesktopSize(width, height, layout);
  121. }
  122. void SMsgReader::readFramebufferUpdateRequest()
  123. {
  124. bool inc = is->readU8();
  125. int x = is->readU16();
  126. int y = is->readU16();
  127. int w = is->readU16();
  128. int h = is->readU16();
  129. handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc);
  130. }
  131. void SMsgReader::readEnableContinuousUpdates()
  132. {
  133. bool enable;
  134. int x, y, w, h;
  135. enable = is->readU8();
  136. x = is->readU16();
  137. y = is->readU16();
  138. w = is->readU16();
  139. h = is->readU16();
  140. handler->enableContinuousUpdates(enable, x, y, w, h);
  141. }
  142. void SMsgReader::readFence()
  143. {
  144. rdr::U32 flags;
  145. rdr::U8 len;
  146. char data[64];
  147. is->skip(3);
  148. flags = is->readU32();
  149. len = is->readU8();
  150. if (len > sizeof(data)) {
  151. vlog.error("Ignoring fence with too large payload");
  152. is->skip(len);
  153. return;
  154. }
  155. is->readBytes(data, len);
  156. handler->fence(flags, len, data);
  157. }
  158. void SMsgReader::readKeyEvent()
  159. {
  160. bool down = is->readU8();
  161. is->skip(2);
  162. rdr::U32 key = is->readU32();
  163. handler->keyEvent(key, 0, down);
  164. }
  165. void SMsgReader::readPointerEvent()
  166. {
  167. int mask = is->readU8();
  168. int x = is->readU16();
  169. int y = is->readU16();
  170. handler->pointerEvent(Point(x, y), mask);
  171. }
  172. void SMsgReader::readClientCutText()
  173. {
  174. is->skip(3);
  175. int len = is->readU32();
  176. if (len < 0) {
  177. throw Exception("Cut text too long.");
  178. }
  179. if (len > maxCutText) {
  180. is->skip(len);
  181. vlog.error("Cut text too long (%d bytes) - ignoring", len);
  182. return;
  183. }
  184. CharArray ca(len);
  185. is->readBytes(ca.buf, len);
  186. CharArray filtered(convertLF(ca.buf, len));
  187. handler->clientCutText(filtered.buf);
  188. }
  189. void SMsgReader::readQEMUMessage()
  190. {
  191. int subType = is->readU8();
  192. switch (subType) {
  193. case qemuExtendedKeyEvent:
  194. readQEMUKeyEvent();
  195. break;
  196. default:
  197. throw Exception("unknown QEMU submessage type %d", subType);
  198. }
  199. }
  200. void SMsgReader::readQEMUKeyEvent()
  201. {
  202. bool down = is->readU16();
  203. rdr::U32 keysym = is->readU32();
  204. rdr::U32 keycode = is->readU32();
  205. if (!keycode) {
  206. vlog.error("Key event without keycode - ignoring");
  207. return;
  208. }
  209. handler->keyEvent(keysym, keycode, down);
  210. }