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