1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 * William Wang 39 */ 40 41/** @file 42 * Declaration of a VNC server 43 */ 44
|
45#ifndef __DEV_VNC_SERVER_HH__
46#define __DEV_VNC_SERVER_HH__
|
45#ifndef __BASE_VNC_VNC_SERVER_HH__ 46#define __BASE_VNC_VNC_SERVER_HH__ |
47 48#include <iostream> 49 50#include "base/vnc/convert.hh"
|
51#include "base/vnc/vncinput.hh" |
52#include "base/bitmap.hh" 53#include "base/circlebuf.hh" 54#include "base/pollevent.hh" 55#include "base/socket.hh" 56#include "cpu/intr_control.hh" 57#include "params/VncServer.hh" 58#include "sim/sim_object.hh" 59
|
59
60/**
61 * A device that expects to receive input from the vnc server should derrive
62 * (through mulitple inheritence if necessary from VncKeyboard or VncMouse
63 * and call setKeyboard() or setMouse() respectively on the vnc server.
|
60/** @file 61 * Declaration of a VNC server |
62 */
|
65class VncKeyboard
66{
67 public:
68 /**
69 * Called when the vnc server receives a key press event from the
70 * client.
71 * @param key the key passed is an x11 keysym
72 * @param down is the key now down or up?
73 */
74 virtual void keyPress(uint32_t key, bool down) = 0;
75};
|
63
|
77class VncMouse
|
64class VncServer : public VncInput |
65{ 66 public:
|
80 /**
81 * called whenever the mouse moves or it's button state changes
82 * buttons is a simple mask with each button (0-8) corresponding to
83 * a bit position in the byte with 1 being down and 0 being up
84 * @param x the x position of the mouse
85 * @param y the y position of the mouse
86 * @param buttos the button state as described above
87 */
88 virtual void mouseAt(uint16_t x, uint16_t y, uint8_t buttons) = 0;
89};
|
67
|
91class VncServer : public SimObject
92{
93 public:
94
|
68 /** 69 * \defgroup VncConstants A set of constants and structs from the VNC spec 70 * @{ 71 */ 72 /** Authentication modes */ 73 const static uint32_t AuthInvalid = 0; 74 const static uint32_t AuthNone = 1; 75 76 /** Error conditions */ 77 const static uint32_t VncOK = 0; 78
|
106 /** Client -> Server message IDs */
107 enum ClientMessages {
108 ClientSetPixelFormat = 0,
109 ClientSetEncodings = 2,
110 ClientFrameBufferUpdate = 3,
111 ClientKeyEvent = 4,
112 ClientPointerEvent = 5,
113 ClientCutText = 6
114 };
115
|
79 /** Server -> Client message IDs */ 80 enum ServerMessages { 81 ServerFrameBufferUpdate = 0, 82 ServerSetColorMapEntries = 1, 83 ServerBell = 2, 84 ServerCutText = 3 85 }; 86 87 /** Encoding types */ 88 enum EncodingTypes { 89 EncodingRaw = 0, 90 EncodingCopyRect = 1, 91 EncodingHextile = 5, 92 EncodingDesktopSize = -223 93 }; 94 95 /** keyboard/mouse support */ 96 enum MouseEvents { 97 MouseLeftButton = 0x1, 98 MouseRightButton = 0x2, 99 MouseMiddleButton = 0x4 100 }; 101 102 const char* vncVersion() const 103 { 104 return "RFB 003.008\n"; 105 } 106 107 enum ConnectionState { 108 WaitForProtocolVersion, 109 WaitForSecurityResponse, 110 WaitForClientInit, 111 InitializationPhase, 112 NormalPhase 113 }; 114
|
152 struct PixelFormat {
153 uint8_t bpp;
154 uint8_t depth;
155 uint8_t bigendian;
156 uint8_t truecolor;
157 uint16_t redmax;
158 uint16_t greenmax;
159 uint16_t bluemax;
160 uint8_t redshift;
161 uint8_t greenshift;
162 uint8_t blueshift;
163 uint8_t padding[3];
164 } M5_ATTR_PACKED;
165
|
115 struct ServerInitMsg { 116 uint16_t fbWidth; 117 uint16_t fbHeight; 118 PixelFormat px; 119 uint32_t namelen; 120 char name[2]; // just to put M5 in here 121 } M5_ATTR_PACKED; 122
|
174 struct PixelFormatMessage {
175 uint8_t type;
176 uint8_t padding[3];
177 PixelFormat px;
178 } M5_ATTR_PACKED;
179
180 struct PixelEncodingsMessage {
181 uint8_t type;
182 uint8_t padding;
183 uint16_t num_encodings;
184 } M5_ATTR_PACKED;
185
186 struct FrameBufferUpdateReq {
187 uint8_t type;
188 uint8_t incremental;
189 uint16_t x;
190 uint16_t y;
191 uint16_t width;
192 uint16_t height;
193 } M5_ATTR_PACKED;
194
195 struct KeyEventMessage {
196 uint8_t type;
197 uint8_t down_flag;
198 uint8_t padding[2];
199 uint32_t key;
200 } M5_ATTR_PACKED;
201
202 struct PointerEventMessage {
203 uint8_t type;
204 uint8_t button_mask;
205 uint16_t x;
206 uint16_t y;
207 } M5_ATTR_PACKED;
208
209 struct ClientCutTextMessage {
210 uint8_t type;
211 uint8_t padding[3];
212 uint32_t length;
213 } M5_ATTR_PACKED;
214
|
123 struct FrameBufferUpdate { 124 uint8_t type; 125 uint8_t padding; 126 uint16_t num_rects; 127 } M5_ATTR_PACKED; 128 129 struct FrameBufferRect { 130 uint16_t x; 131 uint16_t y; 132 uint16_t width; 133 uint16_t height; 134 int32_t encoding; 135 } M5_ATTR_PACKED; 136 137 struct ServerCutText { 138 uint8_t type; 139 uint8_t padding[3]; 140 uint32_t length; 141 } M5_ATTR_PACKED; 142 143 /** @} */ 144 145 protected: 146 /** ListenEvent to accept a vnc client connection */ 147 class ListenEvent: public PollEvent 148 { 149 protected: 150 VncServer *vncserver; 151 152 public: 153 ListenEvent(VncServer *vs, int fd, int e); 154 void process(int revent); 155 }; 156 157 friend class ListenEvent; 158 ListenEvent *listenEvent; 159 160 /** DataEvent to read data from vnc */ 161 class DataEvent: public PollEvent 162 { 163 protected: 164 VncServer *vncserver; 165 166 public: 167 DataEvent(VncServer *vs, int fd, int e); 168 void process(int revent); 169 }; 170 171 friend class DataEvent; 172 DataEvent *dataEvent; 173 174 int number; 175 int dataFd; // data stream file describer 176 177 ListenSocket listener; 178 179 void listen(int port); 180 void accept(); 181 void data(); 182 void detach(); 183 184 public: 185 typedef VncServerParams Params; 186 VncServer(const Params *p); 187 ~VncServer(); 188 189 // RFB 190 protected: 191 192 /** The rfb prototol state the connection is in */ 193 ConnectionState curState; 194
|
287 /** the width of the frame buffer we are sending to the client */
288 uint16_t _videoWidth;
289
290 /** the height of the frame buffer we are sending to the client */
291 uint16_t _videoHeight;
292
293 /** pointer to the actual data that is stored in the frame buffer device */
294 uint8_t* clientRfb;
295
296 /** The device to notify when we get key events */
297 VncKeyboard *keyboard;
298
299 /** The device to notify when we get mouse events */
300 VncMouse *mouse;
301
|
195 /** An update needs to be sent to the client. Without doing this the 196 * client will constantly request data that is pointless */ 197 bool sendUpdate; 198 199 /** The one and only pixel format we support */ 200 PixelFormat pixelFormat; 201 202 /** If the vnc client supports receiving raw data. It always should */ 203 bool supportsRawEnc; 204 205 /** If the vnc client supports the desktop resize command */ 206 bool supportsResizeEnc; 207
|
315 /** The mode of data we're getting frame buffer in */
316 VideoConvert::Mode videoMode;
317
318 /** The video converter that transforms data for us */
319 VideoConvert *vc;
320
321 /** Flag indicating whether to capture snapshots of frame buffer or not */
322 bool captureEnabled;
323
324 /** Current frame number being captured to a file */
325 int captureCurrentFrame;
326
327 /** Directory to store captured frames to */
328 std::string captureOutputDirectory;
329
330 /** Computed hash of the last captured frame */
331 uint64_t captureLastHash;
332
333 /** Cached bitmap object for writing out frame buffers to file */
334 Bitmap *captureBitmap;
335
|
208 protected:
|
337 /** Captures the current frame buffer to a file */
338 void captureFrameBuffer();
339
|
209 /** 210 * vnc client Interface 211 */ 212 213 /** Send an error message to the client 214 * @param error_msg text to send describing the error 215 */ 216 void sendError(const char* error_msg); 217 218 /** Read some data from the client 219 * @param buf the data to read 220 * @param len the amount of data to read 221 * @return length read 222 */ 223 size_t read(uint8_t *buf, size_t len); 224 225 /** Read len -1 bytes from the client into the buffer provided + 1 226 * assert that we read enough bytes. This function exists to handle 227 * reading all of the protocol structs above when we've already read 228 * the first byte which describes which one we're reading 229 * @param buf the address of the buffer to add one to and read data into 230 * @param len the amount of data + 1 to read 231 * @return length read 232 */ 233 size_t read1(uint8_t *buf, size_t len); 234 235 236 /** Templated version of the read function above to 237 * read simple data to the client 238 * @param val data to recv from the client 239 */ 240 template <typename T> size_t read(T* val); 241 242 243 /** Write a buffer to the client. 244 * @param buf buffer to send 245 * @param len length of the buffer 246 * @return number of bytes sent 247 */ 248 size_t write(const uint8_t *buf, size_t len); 249 250 /** Templated version of the write function above to 251 * write simple data to the client 252 * @param val data to send to the client 253 */ 254 template <typename T> size_t write(T* val); 255 256 /** Send a string to the client 257 * @param str string to transmit 258 */ 259 size_t write(const char* str); 260 261 /** Check the client's protocol verion for compatibility and send 262 * the security types we support 263 */ 264 void checkProtocolVersion(); 265 266 /** Check that the security exchange was successful 267 */ 268 void checkSecurity(); 269 270 /** Send client our idea about what the frame buffer looks like */ 271 void sendServerInit(); 272 273 /** Send an error message to the client when something goes wrong 274 * @param error_msg error to send 275 */ 276 void sendError(std::string error_msg); 277 278 /** Send a updated frame buffer to the client. 279 * @todo this doesn't do anything smart and just sends the entire image 280 */ 281 void sendFrameBufferUpdate(); 282 283 /** Receive pixel foramt message from client and process it. */ 284 void setPixelFormat(); 285 286 /** Receive encodings message from client and process it. */ 287 void setEncodings(); 288 289 /** Receive message from client asking for updated frame buffer */ 290 void requestFbUpdate(); 291 292 /** Receive message from client providing new keyboard input */ 293 void recvKeyboardInput(); 294 295 /** Recv message from client providing new mouse movement or button click */ 296 void recvPointerInput(); 297 298 /** Receive message from client that there is text in it's paste buffer. 299 * This is a no-op at the moment, but perhaps we would want to be able to 300 * paste it at some point. 301 */ 302 void recvCutText(); 303 304 /** Tell the client that the frame buffer resized. This happens when the 305 * simulated system changes video modes (E.g. X11 starts). 306 */ 307 void sendFrameBufferResized(); 308 309 public:
|
441 /** Set the address of the frame buffer we are going to show.
442 * To avoid copying, just have the display controller
443 * tell us where the data is instead of constanly copying it around
444 * @param rfb frame buffer that we're going to use
445 */
446 void
447 setFramebufferAddr(uint8_t* rfb)
448 {
449 clientRfb = rfb;
450 }
451
452 /** Set up the device that would like to receive notifications when keys are
453 * pressed in the vnc client keyboard
454 * @param _keyboard an object that derrives from VncKeyboard
455 */
456 void setKeyboard(VncKeyboard *_keyboard) { keyboard = _keyboard; }
457
458 /** Setup the device that would like to receive notifications when mouse
459 * movements or button presses are received from the vnc client.
460 * @param _mouse an object that derrives from VncMouse
461 */
462 void setMouse(VncMouse *_mouse) { mouse = _mouse; }
463
|
310 /** The frame buffer uses this call to notify the vnc server that 311 * the frame buffer has been updated and a new image needs to be sent to the 312 * client 313 */ 314 void 315 setDirty() 316 {
|
317 VncInput::setDirty(); |
318 sendUpdate = true;
|
472 if (captureEnabled)
473 captureFrameBuffer();
|
319 sendFrameBufferUpdate(); 320 } 321
|
477 /** What is the width of the screen we're displaying.
478 * This is used for pointer/tablet devices that need to know to calculate
479 * the correct value to send to the device driver.
480 * @return the width of the simulated screen
481 */
482 uint16_t videoWidth() { return _videoWidth; }
483
484 /** What is the height of the screen we're displaying.
485 * This is used for pointer/tablet devices that need to know to calculate
486 * the correct value to send to the device driver.
487 * @return the height of the simulated screen
488 */
489 uint16_t videoHeight() { return _videoHeight; }
490
|
322 /** Set the mode of the data the frame buffer will be sending us 323 * @param mode the mode 324 */
|
494 void setFrameBufferParams(VideoConvert::Mode mode, int width, int height);
|
325 void setFrameBufferParams(VideoConvert::Mode mode, uint16_t width, 326 uint16_t height); |
327}; 328 329#endif
|