includes: sort all includes
[gem5.git] / src / base / vnc / vncserver.hh
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/vnc/convert.hh"
51 #include "base/circlebuf.hh"
52 #include "base/pollevent.hh"
53 #include "base/socket.hh"
54 #include "cpu/intr_control.hh"
55 #include "params/VncServer.hh"
56 #include "sim/sim_object.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 */
63 class 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
75 class 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
89 class 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