vncserver.hh revision 12020
17949SAli.Saidi@ARM.com/*
210839Sandreas.sandberg@arm.com * Copyright (c) 2010, 2015 ARM Limited
37949SAli.Saidi@ARM.com * All rights reserved
47949SAli.Saidi@ARM.com *
57949SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67949SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77949SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87949SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97949SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107949SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117949SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127949SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137949SAli.Saidi@ARM.com *
147949SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
157949SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
167949SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
177949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
187949SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
197949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
207949SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
217949SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
227949SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
237949SAli.Saidi@ARM.com * this software without specific prior written permission.
247949SAli.Saidi@ARM.com *
257949SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267949SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277949SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287949SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297949SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307949SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317949SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327949SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337949SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347949SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357949SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367949SAli.Saidi@ARM.com *
377949SAli.Saidi@ARM.com * Authors: Ali Saidi
387949SAli.Saidi@ARM.com *          William Wang
397949SAli.Saidi@ARM.com */
407949SAli.Saidi@ARM.com
417949SAli.Saidi@ARM.com/** @file
427949SAli.Saidi@ARM.com * Declaration of a VNC server
437949SAli.Saidi@ARM.com */
447949SAli.Saidi@ARM.com
459330Schander.sudanthi@arm.com#ifndef __BASE_VNC_VNC_SERVER_HH__
469330Schander.sudanthi@arm.com#define __BASE_VNC_VNC_SERVER_HH__
477949SAli.Saidi@ARM.com
487949SAli.Saidi@ARM.com#include <iostream>
497949SAli.Saidi@ARM.com
509330Schander.sudanthi@arm.com#include "base/vnc/vncinput.hh"
518635Schris.emmons@arm.com#include "base/bitmap.hh"
527949SAli.Saidi@ARM.com#include "base/circlebuf.hh"
537949SAli.Saidi@ARM.com#include "base/pollevent.hh"
547949SAli.Saidi@ARM.com#include "base/socket.hh"
558229Snate@binkert.org#include "params/VncServer.hh"
567949SAli.Saidi@ARM.com#include "sim/sim_object.hh"
577949SAli.Saidi@ARM.com
589330Schander.sudanthi@arm.com/** @file
599330Schander.sudanthi@arm.com * Declaration of a VNC server
609330Schander.sudanthi@arm.com */
618635Schris.emmons@arm.com
629330Schander.sudanthi@arm.comclass VncServer : public VncInput
637949SAli.Saidi@ARM.com{
647949SAli.Saidi@ARM.com  public:
657949SAli.Saidi@ARM.com
667949SAli.Saidi@ARM.com    /**
677949SAli.Saidi@ARM.com     * \defgroup VncConstants A set of constants and structs from the VNC spec
687949SAli.Saidi@ARM.com     * @{
697949SAli.Saidi@ARM.com     */
707949SAli.Saidi@ARM.com    /** Authentication modes */
717949SAli.Saidi@ARM.com    const static uint32_t AuthInvalid = 0;
727949SAli.Saidi@ARM.com    const static uint32_t AuthNone    = 1;
737949SAli.Saidi@ARM.com
747949SAli.Saidi@ARM.com    /** Error conditions */
757949SAli.Saidi@ARM.com    const static uint32_t VncOK   = 0;
767949SAli.Saidi@ARM.com
777949SAli.Saidi@ARM.com    /** Server -> Client message IDs */
787949SAli.Saidi@ARM.com    enum ServerMessages {
797949SAli.Saidi@ARM.com        ServerFrameBufferUpdate     = 0,
807949SAli.Saidi@ARM.com        ServerSetColorMapEntries    = 1,
817949SAli.Saidi@ARM.com        ServerBell                  = 2,
827949SAli.Saidi@ARM.com        ServerCutText               = 3
837949SAli.Saidi@ARM.com    };
847949SAli.Saidi@ARM.com
857949SAli.Saidi@ARM.com    /** Encoding types */
867949SAli.Saidi@ARM.com    enum EncodingTypes {
877949SAli.Saidi@ARM.com        EncodingRaw         = 0,
887949SAli.Saidi@ARM.com        EncodingCopyRect    = 1,
897949SAli.Saidi@ARM.com        EncodingHextile     = 5,
907949SAli.Saidi@ARM.com        EncodingDesktopSize = -223
917949SAli.Saidi@ARM.com    };
927949SAli.Saidi@ARM.com
937949SAli.Saidi@ARM.com    /** keyboard/mouse support */
947949SAli.Saidi@ARM.com    enum MouseEvents {
957949SAli.Saidi@ARM.com        MouseLeftButton     = 0x1,
967949SAli.Saidi@ARM.com        MouseRightButton    = 0x2,
977949SAli.Saidi@ARM.com        MouseMiddleButton   = 0x4
987949SAli.Saidi@ARM.com    };
997949SAli.Saidi@ARM.com
1007949SAli.Saidi@ARM.com    const char* vncVersion() const
1017949SAli.Saidi@ARM.com    {
1027949SAli.Saidi@ARM.com        return "RFB 003.008\n";
1037949SAli.Saidi@ARM.com    }
1047949SAli.Saidi@ARM.com
1057949SAli.Saidi@ARM.com    enum ConnectionState {
1067949SAli.Saidi@ARM.com        WaitForProtocolVersion,
1077949SAli.Saidi@ARM.com        WaitForSecurityResponse,
1087949SAli.Saidi@ARM.com        WaitForClientInit,
1097949SAli.Saidi@ARM.com        InitializationPhase,
1107949SAli.Saidi@ARM.com        NormalPhase
1117949SAli.Saidi@ARM.com    };
1127949SAli.Saidi@ARM.com
1137949SAli.Saidi@ARM.com    struct ServerInitMsg {
1147949SAli.Saidi@ARM.com        uint16_t fbWidth;
1157949SAli.Saidi@ARM.com        uint16_t fbHeight;
1167949SAli.Saidi@ARM.com        PixelFormat px;
1177949SAli.Saidi@ARM.com        uint32_t namelen;
1187949SAli.Saidi@ARM.com        char name[2]; // just to put M5 in here
1197949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1207949SAli.Saidi@ARM.com
1217949SAli.Saidi@ARM.com    struct FrameBufferUpdate {
1227949SAli.Saidi@ARM.com        uint8_t type;
1237949SAli.Saidi@ARM.com        uint8_t padding;
1247949SAli.Saidi@ARM.com        uint16_t num_rects;
1257949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1267949SAli.Saidi@ARM.com
1277949SAli.Saidi@ARM.com    struct FrameBufferRect {
1287949SAli.Saidi@ARM.com        uint16_t x;
1297949SAli.Saidi@ARM.com        uint16_t y;
1307949SAli.Saidi@ARM.com        uint16_t width;
1317949SAli.Saidi@ARM.com        uint16_t height;
1327949SAli.Saidi@ARM.com        int32_t encoding;
1337949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1347949SAli.Saidi@ARM.com
1357949SAli.Saidi@ARM.com    struct ServerCutText {
1367949SAli.Saidi@ARM.com        uint8_t type;
1377949SAli.Saidi@ARM.com        uint8_t padding[3];
1387949SAli.Saidi@ARM.com        uint32_t length;
1397949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1407949SAli.Saidi@ARM.com
1417949SAli.Saidi@ARM.com    /** @} */
1427949SAli.Saidi@ARM.com
1437949SAli.Saidi@ARM.com  protected:
1447949SAli.Saidi@ARM.com    /** ListenEvent to accept a vnc client connection */
1457949SAli.Saidi@ARM.com    class ListenEvent: public PollEvent
1467949SAli.Saidi@ARM.com    {
1477949SAli.Saidi@ARM.com      protected:
1487949SAli.Saidi@ARM.com        VncServer *vncserver;
1497949SAli.Saidi@ARM.com
1507949SAli.Saidi@ARM.com      public:
1517949SAli.Saidi@ARM.com        ListenEvent(VncServer *vs, int fd, int e);
1527949SAli.Saidi@ARM.com        void process(int revent);
1537949SAli.Saidi@ARM.com    };
1547949SAli.Saidi@ARM.com
1557949SAli.Saidi@ARM.com    friend class ListenEvent;
1567949SAli.Saidi@ARM.com    ListenEvent *listenEvent;
1577949SAli.Saidi@ARM.com
1587949SAli.Saidi@ARM.com    /** DataEvent to read data from vnc */
1597949SAli.Saidi@ARM.com    class DataEvent: public PollEvent
1607949SAli.Saidi@ARM.com    {
1617949SAli.Saidi@ARM.com      protected:
1627949SAli.Saidi@ARM.com        VncServer *vncserver;
1637949SAli.Saidi@ARM.com
1647949SAli.Saidi@ARM.com      public:
1657949SAli.Saidi@ARM.com        DataEvent(VncServer *vs, int fd, int e);
1667949SAli.Saidi@ARM.com        void process(int revent);
1677949SAli.Saidi@ARM.com    };
1687949SAli.Saidi@ARM.com
1697949SAli.Saidi@ARM.com    friend class DataEvent;
1707949SAli.Saidi@ARM.com    DataEvent *dataEvent;
1717949SAli.Saidi@ARM.com
1727949SAli.Saidi@ARM.com    int number;
1737949SAli.Saidi@ARM.com    int dataFd; // data stream file describer
1747949SAli.Saidi@ARM.com
1757949SAli.Saidi@ARM.com    ListenSocket listener;
1767949SAli.Saidi@ARM.com
1777949SAli.Saidi@ARM.com    void listen(int port);
1787949SAli.Saidi@ARM.com    void accept();
1797949SAli.Saidi@ARM.com    void data();
1807949SAli.Saidi@ARM.com    void detach();
1817949SAli.Saidi@ARM.com
1827949SAli.Saidi@ARM.com  public:
1837949SAli.Saidi@ARM.com    typedef VncServerParams Params;
1847949SAli.Saidi@ARM.com    VncServer(const Params *p);
1857949SAli.Saidi@ARM.com    ~VncServer();
1867949SAli.Saidi@ARM.com
1877949SAli.Saidi@ARM.com    // RFB
1887949SAli.Saidi@ARM.com  protected:
1897949SAli.Saidi@ARM.com
1907949SAli.Saidi@ARM.com    /** The rfb prototol state the connection is in */
1917949SAli.Saidi@ARM.com    ConnectionState curState;
1927949SAli.Saidi@ARM.com
1937949SAli.Saidi@ARM.com    /** An update needs to be sent to the client. Without doing this the
1947949SAli.Saidi@ARM.com     * client will constantly request data that is pointless */
1957949SAli.Saidi@ARM.com    bool sendUpdate;
1967949SAli.Saidi@ARM.com
1977949SAli.Saidi@ARM.com    /** The one and only pixel format we support */
1987949SAli.Saidi@ARM.com    PixelFormat pixelFormat;
1997949SAli.Saidi@ARM.com
2007949SAli.Saidi@ARM.com    /** If the vnc client supports receiving raw data. It always should */
2017949SAli.Saidi@ARM.com    bool supportsRawEnc;
2027949SAli.Saidi@ARM.com
2037949SAli.Saidi@ARM.com    /** If the vnc client supports the desktop resize command */
2047949SAli.Saidi@ARM.com    bool supportsResizeEnc;
2057949SAli.Saidi@ARM.com
2067949SAli.Saidi@ARM.com  protected:
2077949SAli.Saidi@ARM.com    /**
2087949SAli.Saidi@ARM.com     * vnc client Interface
2097949SAli.Saidi@ARM.com     */
2107949SAli.Saidi@ARM.com
2117949SAli.Saidi@ARM.com    /** Send an error message to the client
2127949SAli.Saidi@ARM.com     * @param error_msg text to send describing the error
2137949SAli.Saidi@ARM.com     */
2147949SAli.Saidi@ARM.com    void sendError(const char* error_msg);
2157949SAli.Saidi@ARM.com
2167949SAli.Saidi@ARM.com    /** Read some data from the client
2177949SAli.Saidi@ARM.com     * @param buf the data to read
2187949SAli.Saidi@ARM.com     * @param len the amount of data to read
21912020Sgabeblack@google.com     * @return whether the read was successful
2207949SAli.Saidi@ARM.com     */
22112020Sgabeblack@google.com    bool read(uint8_t *buf, size_t len);
2227949SAli.Saidi@ARM.com
2237949SAli.Saidi@ARM.com    /** Read len -1 bytes from the client into the buffer provided + 1
2247949SAli.Saidi@ARM.com     * assert that we read enough bytes. This function exists to handle
2257949SAli.Saidi@ARM.com     * reading all of the protocol structs above when we've already read
2267949SAli.Saidi@ARM.com     * the first byte which describes which one we're reading
2277949SAli.Saidi@ARM.com     * @param buf the address of the buffer to add one to and read data into
2287949SAli.Saidi@ARM.com     * @param len the amount of data  + 1 to read
22912020Sgabeblack@google.com     * @return whether the read was successful.
2307949SAli.Saidi@ARM.com     */
23112020Sgabeblack@google.com    bool read1(uint8_t *buf, size_t len);
2327949SAli.Saidi@ARM.com
2337949SAli.Saidi@ARM.com
2347949SAli.Saidi@ARM.com    /** Templated version of the read function above to
2357949SAli.Saidi@ARM.com     * read simple data to the client
2367949SAli.Saidi@ARM.com     * @param val data to recv from the client
2377949SAli.Saidi@ARM.com     */
23812020Sgabeblack@google.com    template <typename T> bool read(T* val);
2397949SAli.Saidi@ARM.com
2407949SAli.Saidi@ARM.com
2417949SAli.Saidi@ARM.com    /** Write a buffer to the client.
2427949SAli.Saidi@ARM.com     * @param buf buffer to send
2437949SAli.Saidi@ARM.com     * @param len length of the buffer
24412020Sgabeblack@google.com     * @return whether the write was successful
2457949SAli.Saidi@ARM.com     */
24612020Sgabeblack@google.com    bool write(const uint8_t *buf, size_t len);
2477949SAli.Saidi@ARM.com
2487949SAli.Saidi@ARM.com    /** Templated version of the write function above to
2497949SAli.Saidi@ARM.com     * write simple data to the client
2507949SAli.Saidi@ARM.com     * @param val data to send to the client
2517949SAli.Saidi@ARM.com     */
25212020Sgabeblack@google.com    template <typename T> bool write(T* val);
2537949SAli.Saidi@ARM.com
2547949SAli.Saidi@ARM.com    /** Send a string to the client
2557949SAli.Saidi@ARM.com     * @param str string to transmit
2567949SAli.Saidi@ARM.com     */
25712020Sgabeblack@google.com    bool write(const char* str);
2587949SAli.Saidi@ARM.com
2597949SAli.Saidi@ARM.com    /** Check the client's protocol verion for compatibility and send
2607949SAli.Saidi@ARM.com     * the security types we support
2617949SAli.Saidi@ARM.com     */
2627949SAli.Saidi@ARM.com    void checkProtocolVersion();
2637949SAli.Saidi@ARM.com
2647949SAli.Saidi@ARM.com    /** Check that the security exchange was successful
2657949SAli.Saidi@ARM.com     */
2667949SAli.Saidi@ARM.com    void checkSecurity();
2677949SAli.Saidi@ARM.com
2687949SAli.Saidi@ARM.com    /** Send client our idea about what the frame buffer looks like */
2697949SAli.Saidi@ARM.com    void sendServerInit();
2707949SAli.Saidi@ARM.com
2717949SAli.Saidi@ARM.com    /** Send an error message to the client when something goes wrong
2727949SAli.Saidi@ARM.com     * @param error_msg error to send
2737949SAli.Saidi@ARM.com     */
2747949SAli.Saidi@ARM.com    void sendError(std::string error_msg);
2757949SAli.Saidi@ARM.com
2767949SAli.Saidi@ARM.com    /** Send a updated frame buffer to the client.
2777949SAli.Saidi@ARM.com     * @todo this doesn't do anything smart and just sends the entire image
2787949SAli.Saidi@ARM.com     */
2797949SAli.Saidi@ARM.com    void sendFrameBufferUpdate();
2807949SAli.Saidi@ARM.com
2817949SAli.Saidi@ARM.com    /** Receive pixel foramt message from client and process it. */
2827949SAli.Saidi@ARM.com    void setPixelFormat();
2837949SAli.Saidi@ARM.com
2847949SAli.Saidi@ARM.com    /** Receive encodings message from client and process it. */
2857949SAli.Saidi@ARM.com    void setEncodings();
2867949SAli.Saidi@ARM.com
2877949SAli.Saidi@ARM.com    /** Receive message from client asking for updated frame buffer */
2887949SAli.Saidi@ARM.com    void requestFbUpdate();
2897949SAli.Saidi@ARM.com
2907949SAli.Saidi@ARM.com    /** Receive message from client providing new keyboard input */
2917949SAli.Saidi@ARM.com    void recvKeyboardInput();
2927949SAli.Saidi@ARM.com
2937949SAli.Saidi@ARM.com    /** Recv message from client providing new mouse movement or button click */
2947949SAli.Saidi@ARM.com    void recvPointerInput();
2957949SAli.Saidi@ARM.com
2967949SAli.Saidi@ARM.com    /**  Receive message from client that there is text in it's paste buffer.
2977949SAli.Saidi@ARM.com     * This is a no-op at the moment, but perhaps we would want to be able to
2987949SAli.Saidi@ARM.com     * paste it at some point.
2997949SAli.Saidi@ARM.com     */
3007949SAli.Saidi@ARM.com    void recvCutText();
3017949SAli.Saidi@ARM.com
3027949SAli.Saidi@ARM.com    /** Tell the client that the frame buffer resized. This happens when the
3037949SAli.Saidi@ARM.com     * simulated system changes video modes (E.g. X11 starts).
3047949SAli.Saidi@ARM.com     */
3057949SAli.Saidi@ARM.com    void sendFrameBufferResized();
3067949SAli.Saidi@ARM.com
30710839Sandreas.sandberg@arm.com    static const PixelConverter pixelConverter;
30810839Sandreas.sandberg@arm.com
3097949SAli.Saidi@ARM.com  public:
31011168Sandreas.hansson@arm.com    void setDirty() override;
31111168Sandreas.hansson@arm.com    void frameBufferResized() override;
3127949SAli.Saidi@ARM.com};
3137949SAli.Saidi@ARM.com
3147949SAli.Saidi@ARM.com#endif
315