Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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/OutStream.h>
  21. #include <rfb/msgTypes.h>
  22. #include <rfb/fenceTypes.h>
  23. #include <rfb/encodings.h>
  24. #include <rfb/Exception.h>
  25. #include <rfb/PixelFormat.h>
  26. #include <rfb/Rect.h>
  27. #include <rfb/ConnParams.h>
  28. #include <rfb/Decoder.h>
  29. #include <rfb/CMsgWriter.h>
  30. using namespace rfb;
  31. CMsgWriter::CMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
  32. : cp(cp_), os(os_)
  33. {
  34. }
  35. CMsgWriter::~CMsgWriter()
  36. {
  37. }
  38. void CMsgWriter::writeClientInit(bool shared)
  39. {
  40. os->writeU8(shared);
  41. endMsg();
  42. }
  43. void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
  44. {
  45. startMsg(msgTypeSetPixelFormat);
  46. os->pad(3);
  47. pf.write(os);
  48. endMsg();
  49. }
  50. void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
  51. {
  52. startMsg(msgTypeSetEncodings);
  53. os->skip(1);
  54. os->writeU16(nEncodings);
  55. for (int i = 0; i < nEncodings; i++)
  56. os->writeU32(encodings[i]);
  57. endMsg();
  58. }
  59. // Ask for encodings based on which decoders are supported. Assumes higher
  60. // encoding numbers are more desirable.
  61. void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
  62. {
  63. int nEncodings = 0;
  64. rdr::U32 encodings[encodingMax+3];
  65. if (cp->supportsLocalCursor) {
  66. encodings[nEncodings++] = pseudoEncodingCursorWithAlpha;
  67. encodings[nEncodings++] = pseudoEncodingCursor;
  68. encodings[nEncodings++] = pseudoEncodingXCursor;
  69. }
  70. if (cp->supportsDesktopResize)
  71. encodings[nEncodings++] = pseudoEncodingDesktopSize;
  72. if (cp->supportsExtendedDesktopSize)
  73. encodings[nEncodings++] = pseudoEncodingExtendedDesktopSize;
  74. if (cp->supportsDesktopRename)
  75. encodings[nEncodings++] = pseudoEncodingDesktopName;
  76. if (cp->supportsLEDState)
  77. encodings[nEncodings++] = pseudoEncodingLEDState;
  78. encodings[nEncodings++] = pseudoEncodingLastRect;
  79. encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
  80. encodings[nEncodings++] = pseudoEncodingFence;
  81. if (Decoder::supported(preferredEncoding)) {
  82. encodings[nEncodings++] = preferredEncoding;
  83. }
  84. if (useCopyRect) {
  85. encodings[nEncodings++] = encodingCopyRect;
  86. }
  87. /*
  88. * Prefer encodings in this order:
  89. *
  90. * Tight, ZRLE, Hextile, *
  91. */
  92. if ((preferredEncoding != encodingTight) &&
  93. Decoder::supported(encodingTight))
  94. encodings[nEncodings++] = encodingTight;
  95. if ((preferredEncoding != encodingZRLE) &&
  96. Decoder::supported(encodingZRLE))
  97. encodings[nEncodings++] = encodingZRLE;
  98. if ((preferredEncoding != encodingHextile) &&
  99. Decoder::supported(encodingHextile))
  100. encodings[nEncodings++] = encodingHextile;
  101. // Remaining encodings
  102. for (int i = encodingMax; i >= 0; i--) {
  103. switch (i) {
  104. case encodingCopyRect:
  105. case encodingTight:
  106. case encodingZRLE:
  107. case encodingHextile:
  108. /* These have already been sent earlier */
  109. break;
  110. default:
  111. if ((i != preferredEncoding) && Decoder::supported(i))
  112. encodings[nEncodings++] = i;
  113. }
  114. }
  115. if (cp->compressLevel >= 0 && cp->compressLevel <= 9)
  116. encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel;
  117. if (cp->qualityLevel >= 0 && cp->qualityLevel <= 9)
  118. encodings[nEncodings++] = pseudoEncodingQualityLevel0 + cp->qualityLevel;
  119. writeSetEncodings(nEncodings, encodings);
  120. }
  121. void CMsgWriter::writeSetDesktopSize(int width, int height,
  122. const ScreenSet& layout)
  123. {
  124. if (!cp->supportsSetDesktopSize)
  125. throw Exception("Server does not support SetDesktopSize");
  126. startMsg(msgTypeSetDesktopSize);
  127. os->pad(1);
  128. os->writeU16(width);
  129. os->writeU16(height);
  130. os->writeU8(layout.num_screens());
  131. os->pad(1);
  132. ScreenSet::const_iterator iter;
  133. for (iter = layout.begin();iter != layout.end();++iter) {
  134. os->writeU32(iter->id);
  135. os->writeU16(iter->dimensions.tl.x);
  136. os->writeU16(iter->dimensions.tl.y);
  137. os->writeU16(iter->dimensions.width());
  138. os->writeU16(iter->dimensions.height());
  139. os->writeU32(iter->flags);
  140. }
  141. endMsg();
  142. }
  143. void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
  144. {
  145. startMsg(msgTypeFramebufferUpdateRequest);
  146. os->writeU8(incremental);
  147. os->writeU16(r.tl.x);
  148. os->writeU16(r.tl.y);
  149. os->writeU16(r.width());
  150. os->writeU16(r.height());
  151. endMsg();
  152. }
  153. void CMsgWriter::writeEnableContinuousUpdates(bool enable,
  154. int x, int y, int w, int h)
  155. {
  156. if (!cp->supportsContinuousUpdates)
  157. throw Exception("Server does not support continuous updates");
  158. startMsg(msgTypeEnableContinuousUpdates);
  159. os->writeU8(!!enable);
  160. os->writeU16(x);
  161. os->writeU16(y);
  162. os->writeU16(w);
  163. os->writeU16(h);
  164. endMsg();
  165. }
  166. void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
  167. {
  168. if (!cp->supportsFence)
  169. throw Exception("Server does not support fences");
  170. if (len > 64)
  171. throw Exception("Too large fence payload");
  172. if ((flags & ~fenceFlagsSupported) != 0)
  173. throw Exception("Unknown fence flags");
  174. startMsg(msgTypeClientFence);
  175. os->pad(3);
  176. os->writeU32(flags);
  177. os->writeU8(len);
  178. os->writeBytes(data, len);
  179. endMsg();
  180. }
  181. void CMsgWriter::keyEvent(rdr::U32 key, bool down)
  182. {
  183. startMsg(msgTypeKeyEvent);
  184. os->writeU8(down);
  185. os->pad(2);
  186. os->writeU32(key);
  187. endMsg();
  188. }
  189. void CMsgWriter::pointerEvent(const Point& pos, int buttonMask)
  190. {
  191. Point p(pos);
  192. if (p.x < 0) p.x = 0;
  193. if (p.y < 0) p.y = 0;
  194. if (p.x >= cp->width) p.x = cp->width - 1;
  195. if (p.y >= cp->height) p.y = cp->height - 1;
  196. startMsg(msgTypePointerEvent);
  197. os->writeU8(buttonMask);
  198. os->writeU16(p.x);
  199. os->writeU16(p.y);
  200. endMsg();
  201. }
  202. void CMsgWriter::clientCutText(const char* str, rdr::U32 len)
  203. {
  204. startMsg(msgTypeClientCutText);
  205. os->pad(3);
  206. os->writeU32(len);
  207. os->writeBytes(str, len);
  208. endMsg();
  209. }
  210. void CMsgWriter::startMsg(int type)
  211. {
  212. os->writeU8(type);
  213. }
  214. void CMsgWriter::endMsg()
  215. {
  216. os->flush();
  217. }