1/* 2 * Copyright (c) 2010, 2015 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 __BASE_VNC_VNC_SERVER_HH__ 46#define __BASE_VNC_VNC_SERVER_HH__ 47 48#include <iostream> 49 50#include "base/vnc/vncinput.hh" 51#include "base/circlebuf.hh" 52#include "base/pollevent.hh" 53#include "base/socket.hh" 54#include "params/VncServer.hh" 55#include "sim/sim_object.hh" 56 57/** @file 58 * Declaration of a VNC server 59 */ 60 61class VncServer : public VncInput 62{ 63 public: 64 65 /** 66 * \defgroup VncConstants A set of constants and structs from the VNC spec 67 * @{ 68 */ 69 /** Authentication modes */ 70 const static uint32_t AuthInvalid = 0; 71 const static uint32_t AuthNone = 1; 72 73 /** Error conditions */ 74 const static uint32_t VncOK = 0; 75 76 /** Server -> Client message IDs */ 77 enum ServerMessages { 78 ServerFrameBufferUpdate = 0, 79 ServerSetColorMapEntries = 1, 80 ServerBell = 2, 81 ServerCutText = 3 82 }; 83 84 /** Encoding types */ 85 enum EncodingTypes { 86 EncodingRaw = 0, 87 EncodingCopyRect = 1, 88 EncodingHextile = 5, 89 EncodingDesktopSize = -223 90 }; 91 92 /** keyboard/mouse support */ 93 enum MouseEvents { 94 MouseLeftButton = 0x1, 95 MouseRightButton = 0x2, 96 MouseMiddleButton = 0x4 97 }; 98 99 const char* vncVersion() const 100 { 101 return "RFB 003.008\n"; 102 } 103 104 enum ConnectionState { 105 WaitForProtocolVersion, 106 WaitForSecurityResponse, 107 WaitForClientInit, 108 InitializationPhase, 109 NormalPhase 110 }; 111 112 struct ServerInitMsg { 113 uint16_t fbWidth; 114 uint16_t fbHeight; 115 PixelFormat px; 116 uint32_t namelen; 117 char name[2]; // just to put M5 in here 118 } M5_ATTR_PACKED; 119 120 struct FrameBufferUpdate { 121 uint8_t type; 122 uint8_t padding; 123 uint16_t num_rects; 124 } M5_ATTR_PACKED; 125 126 struct FrameBufferRect { 127 uint16_t x; 128 uint16_t y; 129 uint16_t width; 130 uint16_t height; 131 int32_t encoding; 132 } M5_ATTR_PACKED; 133 134 struct ServerCutText { 135 uint8_t type; 136 uint8_t padding[3]; 137 uint32_t length; 138 } M5_ATTR_PACKED; 139 140 /** @} */ 141 142 protected: 143 /** ListenEvent to accept a vnc client connection */ 144 class ListenEvent: public PollEvent 145 { 146 protected: 147 VncServer *vncserver; 148 149 public: 150 ListenEvent(VncServer *vs, int fd, int e); 151 void process(int revent); 152 }; 153 154 friend class ListenEvent; 155 ListenEvent *listenEvent; 156 157 /** DataEvent to read data from vnc */ 158 class DataEvent: public PollEvent 159 { 160 protected: 161 VncServer *vncserver; 162 163 public: 164 DataEvent(VncServer *vs, int fd, int e); 165 void process(int revent); 166 }; 167 168 friend class DataEvent; 169 DataEvent *dataEvent; 170 171 int number; 172 int dataFd; // data stream file describer 173 174 ListenSocket listener; 175 176 void listen(int port); 177 void accept(); 178 void data(); 179 void detach(); 180 181 public: 182 typedef VncServerParams Params; 183 VncServer(const Params *p); 184 ~VncServer(); 185 186 // RFB 187 protected: 188 189 /** The rfb prototol state the connection is in */ 190 ConnectionState curState; 191 192 /** An update needs to be sent to the client. Without doing this the 193 * client will constantly request data that is pointless */ 194 bool sendUpdate; 195 196 /** The one and only pixel format we support */ 197 PixelFormat pixelFormat; 198 199 /** If the vnc client supports receiving raw data. It always should */ 200 bool supportsRawEnc; 201 202 /** If the vnc client supports the desktop resize command */ 203 bool supportsResizeEnc; 204 205 protected: 206 /** 207 * vnc client Interface 208 */ 209 210 /** Send an error message to the client 211 * @param error_msg text to send describing the error 212 */ 213 void sendError(const char* error_msg); 214 215 /** Read some data from the client 216 * @param buf the data to read 217 * @param len the amount of data to read 218 * @return whether the read was successful 219 */ 220 bool read(uint8_t *buf, size_t len); 221 222 /** Read len -1 bytes from the client into the buffer provided + 1 223 * assert that we read enough bytes. This function exists to handle 224 * reading all of the protocol structs above when we've already read 225 * the first byte which describes which one we're reading 226 * @param buf the address of the buffer to add one to and read data into 227 * @param len the amount of data + 1 to read 228 * @return whether the read was successful. 229 */ 230 bool read1(uint8_t *buf, size_t len); 231 232 233 /** Templated version of the read function above to 234 * read simple data to the client 235 * @param val data to recv from the client 236 */ 237 template <typename T> bool read(T* val); 238 239 240 /** Write a buffer to the client. 241 * @param buf buffer to send 242 * @param len length of the buffer 243 * @return whether the write was successful 244 */ 245 bool write(const uint8_t *buf, size_t len); 246 247 /** Templated version of the write function above to 248 * write simple data to the client 249 * @param val data to send to the client 250 */ 251 template <typename T> bool write(T* val); 252 253 /** Send a string to the client 254 * @param str string to transmit 255 */ 256 bool write(const char* str); 257 258 /** Check the client's protocol verion for compatibility and send 259 * the security types we support 260 */ 261 void checkProtocolVersion(); 262 263 /** Check that the security exchange was successful 264 */ 265 void checkSecurity(); 266 267 /** Send client our idea about what the frame buffer looks like */ 268 void sendServerInit(); 269 270 /** Send an error message to the client when something goes wrong 271 * @param error_msg error to send 272 */ 273 void sendError(std::string error_msg); 274 275 /** Send a updated frame buffer to the client. 276 * @todo this doesn't do anything smart and just sends the entire image 277 */ 278 void sendFrameBufferUpdate(); 279 280 /** Receive pixel foramt message from client and process it. */ 281 void setPixelFormat(); 282 283 /** Receive encodings message from client and process it. */ 284 void setEncodings(); 285 286 /** Receive message from client asking for updated frame buffer */ 287 void requestFbUpdate(); 288 289 /** Receive message from client providing new keyboard input */ 290 void recvKeyboardInput(); 291 292 /** Recv message from client providing new mouse movement or button click */ 293 void recvPointerInput(); 294 295 /** Receive message from client that there is text in it's paste buffer. 296 * This is a no-op at the moment, but perhaps we would want to be able to 297 * paste it at some point. 298 */ 299 void recvCutText(); 300 301 /** Tell the client that the frame buffer resized. This happens when the 302 * simulated system changes video modes (E.g. X11 starts). 303 */ 304 void sendFrameBufferResized(); 305 306 static const PixelConverter pixelConverter; 307 308 public: 309 void setDirty() override; 310 void frameBufferResized() override; 311}; 312 313#endif 314