vncserver.hh revision 7949
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__ 47 48#include <iostream> 49 50#include "base/circlebuf.hh" 51#include "base/pollevent.hh" 52#include "base/socket.hh" 53#include "base/vnc/convert.hh" 54#include "cpu/intr_control.hh" 55#include "sim/sim_object.hh" 56#include "params/VncServer.hh" 57 58/** 59 * A device that expects to receive input from the vnc server should derrive 60 * (through mulitple inheritence if necessary from VncKeyboard or VncMouse 61 * and call setKeyboard() or setMouse() respectively on the vnc server. 62 */ 63class VncKeyboard 64{ 65 public: 66 /** 67 * Called when the vnc server receives a key press event from the 68 * client. 69 * @param key the key passed is an x11 keysym 70 * @param down is the key now down or up? 71 */ 72 virtual void keyPress(uint32_t key, bool down) = 0; 73}; 74 75class VncMouse 76{ 77 public: 78 /** 79 * called whenever the mouse moves or it's button state changes 80 * buttons is a simple mask with each button (0-8) corresponding to 81 * a bit position in the byte with 1 being down and 0 being up 82 * @param x the x position of the mouse 83 * @param y the y position of the mouse 84 * @param buttos the button state as described above 85 */ 86 virtual void mouseAt(uint16_t x, uint16_t y, uint8_t buttons) = 0; 87}; 88 89class VncServer : public SimObject 90{ 91 public: 92 93 /** 94 * \defgroup VncConstants A set of constants and structs from the VNC spec 95 * @{ 96 */ 97 /** Authentication modes */ 98 const static uint32_t AuthInvalid = 0; 99 const static uint32_t AuthNone = 1; 100 101 /** Error conditions */ 102 const static uint32_t VncOK = 0; 103 104 /** Client -> Server message IDs */ 105 enum ClientMessages { 106 ClientSetPixelFormat = 0, 107 ClientSetEncodings = 2, 108 ClientFrameBufferUpdate = 3, 109 ClientKeyEvent = 4, 110 ClientPointerEvent = 5, 111 ClientCutText = 6 112 }; 113 114 /** Server -> Client message IDs */ 115 enum ServerMessages { 116 ServerFrameBufferUpdate = 0, 117 ServerSetColorMapEntries = 1, 118 ServerBell = 2, 119 ServerCutText = 3 120 }; 121 122 /** Encoding types */ 123 enum EncodingTypes { 124 EncodingRaw = 0, 125 EncodingCopyRect = 1, 126 EncodingHextile = 5, 127 EncodingDesktopSize = -223 128 }; 129 130 /** keyboard/mouse support */ 131 enum MouseEvents { 132 MouseLeftButton = 0x1, 133 MouseRightButton = 0x2, 134 MouseMiddleButton = 0x4 135 }; 136 137 const char* vncVersion() const 138 { 139 return "RFB 003.008\n"; 140 } 141 142 enum ConnectionState { 143 WaitForProtocolVersion, 144 WaitForSecurityResponse, 145 WaitForClientInit, 146 InitializationPhase, 147 NormalPhase 148 }; 149 150 struct PixelFormat { 151 uint8_t bpp; 152 uint8_t depth; 153 uint8_t bigendian; 154 uint8_t truecolor; 155 uint16_t redmax; 156 uint16_t greenmax; 157 uint16_t bluemax; 158 uint8_t redshift; 159 uint8_t greenshift; 160 uint8_t blueshift; 161 uint8_t padding[3]; 162 } M5_ATTR_PACKED; 163 164 struct ServerInitMsg { 165 uint16_t fbWidth; 166 uint16_t fbHeight; 167 PixelFormat px; 168 uint32_t namelen; 169 char name[2]; // just to put M5 in here 170 } M5_ATTR_PACKED; 171 172 struct PixelFormatMessage { 173 uint8_t type; 174 uint8_t padding[3]; 175 PixelFormat px; 176 } M5_ATTR_PACKED; 177 178 struct PixelEncodingsMessage { 179 uint8_t type; 180 uint8_t padding; 181 uint16_t num_encodings; 182 } M5_ATTR_PACKED; 183 184 struct FrameBufferUpdateReq { 185 uint8_t type; 186 uint8_t incremental; 187 uint16_t x; 188 uint16_t y; 189 uint16_t width; 190 uint16_t height; 191 } M5_ATTR_PACKED; 192 193 struct KeyEventMessage { 194 uint8_t type; 195 uint8_t down_flag; 196 uint8_t padding[2]; 197 uint32_t key; 198 } M5_ATTR_PACKED; 199 200 struct PointerEventMessage { 201 uint8_t type; 202 uint8_t button_mask; 203 uint16_t x; 204 uint16_t y; 205 } M5_ATTR_PACKED; 206 207 struct ClientCutTextMessage { 208 uint8_t type; 209 uint8_t padding[3]; 210 uint32_t length; 211 } M5_ATTR_PACKED; 212 213 struct FrameBufferUpdate { 214 uint8_t type; 215 uint8_t padding; 216 uint16_t num_rects; 217 } M5_ATTR_PACKED; 218 219 struct FrameBufferRect { 220 uint16_t x; 221 uint16_t y; 222 uint16_t width; 223 uint16_t height; 224 int32_t encoding; 225 } M5_ATTR_PACKED; 226 227 struct ServerCutText { 228 uint8_t type; 229 uint8_t padding[3]; 230 uint32_t length; 231 } M5_ATTR_PACKED; 232 233 /** @} */ 234 235 protected: 236 /** ListenEvent to accept a vnc client connection */ 237 class ListenEvent: public PollEvent 238 { 239 protected: 240 VncServer *vncserver; 241 242 public: 243 ListenEvent(VncServer *vs, int fd, int e); 244 void process(int revent); 245 }; 246 247 friend class ListenEvent; 248 ListenEvent *listenEvent; 249 250 /** DataEvent to read data from vnc */ 251 class DataEvent: public PollEvent 252 { 253 protected: 254 VncServer *vncserver; 255 256 public: 257 DataEvent(VncServer *vs, int fd, int e); 258 void process(int revent); 259 }; 260 261 friend class DataEvent; 262 DataEvent *dataEvent; 263 264 int number; 265 int dataFd; // data stream file describer 266 267 ListenSocket listener; 268 269 void listen(int port); 270 void accept(); 271 void data(); 272 void detach(); 273 274 public: 275 typedef VncServerParams Params; 276 VncServer(const Params *p); 277 ~VncServer(); 278 279 // RFB 280 protected: 281 282 /** The rfb prototol state the connection is in */ 283 ConnectionState curState; 284 285 /** the width of the frame buffer we are sending to the client */ 286 uint16_t _videoWidth; 287 288 /** the height of the frame buffer we are sending to the client */ 289 uint16_t _videoHeight; 290 291 /** pointer to the actual data that is stored in the frame buffer device */ 292 uint8_t* clientRfb; 293 294 /** The device to notify when we get key events */ 295 VncKeyboard *keyboard; 296 297 /** The device to notify when we get mouse events */ 298 VncMouse *mouse; 299 300 /** An update needs to be sent to the client. Without doing this the 301 * client will constantly request data that is pointless */ 302 bool sendUpdate; 303 304 /** The one and only pixel format we support */ 305 PixelFormat pixelFormat; 306 307 /** If the vnc client supports receiving raw data. It always should */ 308 bool supportsRawEnc; 309 310 /** If the vnc client supports the desktop resize command */ 311 bool supportsResizeEnc; 312 313 /** The mode of data we're getting frame buffer in */ 314 VideoConvert::Mode videoMode; 315 316 /** The video converter that transforms data for us */ 317 VideoConvert *vc; 318 319 protected: 320 /** 321 * vnc client Interface 322 */ 323 324 /** Send an error message to the client 325 * @param error_msg text to send describing the error 326 */ 327 void sendError(const char* error_msg); 328 329 /** Read some data from the client 330 * @param buf the data to read 331 * @param len the amount of data to read 332 * @return length read 333 */ 334 size_t read(uint8_t *buf, size_t len); 335 336 /** Read len -1 bytes from the client into the buffer provided + 1 337 * assert that we read enough bytes. This function exists to handle 338 * reading all of the protocol structs above when we've already read 339 * the first byte which describes which one we're reading 340 * @param buf the address of the buffer to add one to and read data into 341 * @param len the amount of data + 1 to read 342 * @return length read 343 */ 344 size_t read1(uint8_t *buf, size_t len); 345 346 347 /** Templated version of the read function above to 348 * read simple data to the client 349 * @param val data to recv from the client 350 */ 351 template <typename T> size_t read(T* val); 352 353 354 /** Write a buffer to the client. 355 * @param buf buffer to send 356 * @param len length of the buffer 357 * @return number of bytes sent 358 */ 359 size_t write(const uint8_t *buf, size_t len); 360 361 /** Templated version of the write function above to 362 * write simple data to the client 363 * @param val data to send to the client 364 */ 365 template <typename T> size_t write(T* val); 366 367 /** Send a string to the client 368 * @param str string to transmit 369 */ 370 size_t write(const char* str); 371 372 /** Check the client's protocol verion for compatibility and send 373 * the security types we support 374 */ 375 void checkProtocolVersion(); 376 377 /** Check that the security exchange was successful 378 */ 379 void checkSecurity(); 380 381 /** Send client our idea about what the frame buffer looks like */ 382 void sendServerInit(); 383 384 /** Send an error message to the client when something goes wrong 385 * @param error_msg error to send 386 */ 387 void sendError(std::string error_msg); 388 389 /** Send a updated frame buffer to the client. 390 * @todo this doesn't do anything smart and just sends the entire image 391 */ 392 void sendFrameBufferUpdate(); 393 394 /** Receive pixel foramt message from client and process it. */ 395 void setPixelFormat(); 396 397 /** Receive encodings message from client and process it. */ 398 void setEncodings(); 399 400 /** Receive message from client asking for updated frame buffer */ 401 void requestFbUpdate(); 402 403 /** Receive message from client providing new keyboard input */ 404 void recvKeyboardInput(); 405 406 /** Recv message from client providing new mouse movement or button click */ 407 void recvPointerInput(); 408 409 /** Receive message from client that there is text in it's paste buffer. 410 * This is a no-op at the moment, but perhaps we would want to be able to 411 * paste it at some point. 412 */ 413 void recvCutText(); 414 415 /** Tell the client that the frame buffer resized. This happens when the 416 * simulated system changes video modes (E.g. X11 starts). 417 */ 418 void sendFrameBufferResized(); 419 420 public: 421 /** Set the address of the frame buffer we are going to show. 422 * To avoid copying, just have the display controller 423 * tell us where the data is instead of constanly copying it around 424 * @param rfb frame buffer that we're going to use 425 */ 426 void 427 setFramebufferAddr(uint8_t* rfb) 428 { 429 clientRfb = rfb; 430 } 431 432 /** Set up the device that would like to receive notifications when keys are 433 * pressed in the vnc client keyboard 434 * @param _keyboard an object that derrives from VncKeyboard 435 */ 436 void setKeyboard(VncKeyboard *_keyboard) { keyboard = _keyboard; } 437 438 /** Setup the device that would like to receive notifications when mouse 439 * movements or button presses are received from the vnc client. 440 * @param _mouse an object that derrives from VncMouse 441 */ 442 void setMouse(VncMouse *_mouse) { mouse = _mouse; } 443 444 /** The frame buffer uses this call to notify the vnc server that 445 * the frame buffer has been updated and a new image needs to be sent to the 446 * client 447 */ 448 void 449 setDirty() 450 { 451 sendUpdate = true; 452 sendFrameBufferUpdate(); 453 } 454 455 /** What is the width of the screen we're displaying. 456 * This is used for pointer/tablet devices that need to know to calculate 457 * the correct value to send to the device driver. 458 * @return the width of the simulated screen 459 */ 460 uint16_t videoWidth() { return _videoWidth; } 461 462 /** What is the height of the screen we're displaying. 463 * This is used for pointer/tablet devices that need to know to calculate 464 * the correct value to send to the device driver. 465 * @return the height of the simulated screen 466 */ 467 uint16_t videoHeight() { return _videoHeight; } 468 469 /** Set the mode of the data the frame buffer will be sending us 470 * @param mode the mode 471 */ 472 void setFrameBufferParams(VideoConvert::Mode mode, int width, int height); 473}; 474 475#endif 476