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