vncserver.hh revision 9330
17949SAli.Saidi@ARM.com/*
27949SAli.Saidi@ARM.com * Copyright (c) 2010 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
508229Snate@binkert.org#include "base/vnc/convert.hh"
519330Schander.sudanthi@arm.com#include "base/vnc/vncinput.hh"
528635Schris.emmons@arm.com#include "base/bitmap.hh"
537949SAli.Saidi@ARM.com#include "base/circlebuf.hh"
547949SAli.Saidi@ARM.com#include "base/pollevent.hh"
557949SAli.Saidi@ARM.com#include "base/socket.hh"
567949SAli.Saidi@ARM.com#include "cpu/intr_control.hh"
578229Snate@binkert.org#include "params/VncServer.hh"
587949SAli.Saidi@ARM.com#include "sim/sim_object.hh"
597949SAli.Saidi@ARM.com
609330Schander.sudanthi@arm.com/** @file
619330Schander.sudanthi@arm.com * Declaration of a VNC server
629330Schander.sudanthi@arm.com */
638635Schris.emmons@arm.com
649330Schander.sudanthi@arm.comclass VncServer : public VncInput
657949SAli.Saidi@ARM.com{
667949SAli.Saidi@ARM.com  public:
677949SAli.Saidi@ARM.com
687949SAli.Saidi@ARM.com    /**
697949SAli.Saidi@ARM.com     * \defgroup VncConstants A set of constants and structs from the VNC spec
707949SAli.Saidi@ARM.com     * @{
717949SAli.Saidi@ARM.com     */
727949SAli.Saidi@ARM.com    /** Authentication modes */
737949SAli.Saidi@ARM.com    const static uint32_t AuthInvalid = 0;
747949SAli.Saidi@ARM.com    const static uint32_t AuthNone    = 1;
757949SAli.Saidi@ARM.com
767949SAli.Saidi@ARM.com    /** Error conditions */
777949SAli.Saidi@ARM.com    const static uint32_t VncOK   = 0;
787949SAli.Saidi@ARM.com
797949SAli.Saidi@ARM.com    /** Server -> Client message IDs */
807949SAli.Saidi@ARM.com    enum ServerMessages {
817949SAli.Saidi@ARM.com        ServerFrameBufferUpdate     = 0,
827949SAli.Saidi@ARM.com        ServerSetColorMapEntries    = 1,
837949SAli.Saidi@ARM.com        ServerBell                  = 2,
847949SAli.Saidi@ARM.com        ServerCutText               = 3
857949SAli.Saidi@ARM.com    };
867949SAli.Saidi@ARM.com
877949SAli.Saidi@ARM.com    /** Encoding types */
887949SAli.Saidi@ARM.com    enum EncodingTypes {
897949SAli.Saidi@ARM.com        EncodingRaw         = 0,
907949SAli.Saidi@ARM.com        EncodingCopyRect    = 1,
917949SAli.Saidi@ARM.com        EncodingHextile     = 5,
927949SAli.Saidi@ARM.com        EncodingDesktopSize = -223
937949SAli.Saidi@ARM.com    };
947949SAli.Saidi@ARM.com
957949SAli.Saidi@ARM.com    /** keyboard/mouse support */
967949SAli.Saidi@ARM.com    enum MouseEvents {
977949SAli.Saidi@ARM.com        MouseLeftButton     = 0x1,
987949SAli.Saidi@ARM.com        MouseRightButton    = 0x2,
997949SAli.Saidi@ARM.com        MouseMiddleButton   = 0x4
1007949SAli.Saidi@ARM.com    };
1017949SAli.Saidi@ARM.com
1027949SAli.Saidi@ARM.com    const char* vncVersion() const
1037949SAli.Saidi@ARM.com    {
1047949SAli.Saidi@ARM.com        return "RFB 003.008\n";
1057949SAli.Saidi@ARM.com    }
1067949SAli.Saidi@ARM.com
1077949SAli.Saidi@ARM.com    enum ConnectionState {
1087949SAli.Saidi@ARM.com        WaitForProtocolVersion,
1097949SAli.Saidi@ARM.com        WaitForSecurityResponse,
1107949SAli.Saidi@ARM.com        WaitForClientInit,
1117949SAli.Saidi@ARM.com        InitializationPhase,
1127949SAli.Saidi@ARM.com        NormalPhase
1137949SAli.Saidi@ARM.com    };
1147949SAli.Saidi@ARM.com
1157949SAli.Saidi@ARM.com    struct ServerInitMsg {
1167949SAli.Saidi@ARM.com        uint16_t fbWidth;
1177949SAli.Saidi@ARM.com        uint16_t fbHeight;
1187949SAli.Saidi@ARM.com        PixelFormat px;
1197949SAli.Saidi@ARM.com        uint32_t namelen;
1207949SAli.Saidi@ARM.com        char name[2]; // just to put M5 in here
1217949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1227949SAli.Saidi@ARM.com
1237949SAli.Saidi@ARM.com    struct FrameBufferUpdate {
1247949SAli.Saidi@ARM.com        uint8_t type;
1257949SAli.Saidi@ARM.com        uint8_t padding;
1267949SAli.Saidi@ARM.com        uint16_t num_rects;
1277949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1287949SAli.Saidi@ARM.com
1297949SAli.Saidi@ARM.com    struct FrameBufferRect {
1307949SAli.Saidi@ARM.com        uint16_t x;
1317949SAli.Saidi@ARM.com        uint16_t y;
1327949SAli.Saidi@ARM.com        uint16_t width;
1337949SAli.Saidi@ARM.com        uint16_t height;
1347949SAli.Saidi@ARM.com        int32_t encoding;
1357949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1367949SAli.Saidi@ARM.com
1377949SAli.Saidi@ARM.com    struct ServerCutText {
1387949SAli.Saidi@ARM.com        uint8_t type;
1397949SAli.Saidi@ARM.com        uint8_t padding[3];
1407949SAli.Saidi@ARM.com        uint32_t length;
1417949SAli.Saidi@ARM.com    } M5_ATTR_PACKED;
1427949SAli.Saidi@ARM.com
1437949SAli.Saidi@ARM.com    /** @} */
1447949SAli.Saidi@ARM.com
1457949SAli.Saidi@ARM.com  protected:
1467949SAli.Saidi@ARM.com    /** ListenEvent to accept a vnc client connection */
1477949SAli.Saidi@ARM.com    class ListenEvent: public PollEvent
1487949SAli.Saidi@ARM.com    {
1497949SAli.Saidi@ARM.com      protected:
1507949SAli.Saidi@ARM.com        VncServer *vncserver;
1517949SAli.Saidi@ARM.com
1527949SAli.Saidi@ARM.com      public:
1537949SAli.Saidi@ARM.com        ListenEvent(VncServer *vs, int fd, int e);
1547949SAli.Saidi@ARM.com        void process(int revent);
1557949SAli.Saidi@ARM.com    };
1567949SAli.Saidi@ARM.com
1577949SAli.Saidi@ARM.com    friend class ListenEvent;
1587949SAli.Saidi@ARM.com    ListenEvent *listenEvent;
1597949SAli.Saidi@ARM.com
1607949SAli.Saidi@ARM.com    /** DataEvent to read data from vnc */
1617949SAli.Saidi@ARM.com    class DataEvent: public PollEvent
1627949SAli.Saidi@ARM.com    {
1637949SAli.Saidi@ARM.com      protected:
1647949SAli.Saidi@ARM.com        VncServer *vncserver;
1657949SAli.Saidi@ARM.com
1667949SAli.Saidi@ARM.com      public:
1677949SAli.Saidi@ARM.com        DataEvent(VncServer *vs, int fd, int e);
1687949SAli.Saidi@ARM.com        void process(int revent);
1697949SAli.Saidi@ARM.com    };
1707949SAli.Saidi@ARM.com
1717949SAli.Saidi@ARM.com    friend class DataEvent;
1727949SAli.Saidi@ARM.com    DataEvent *dataEvent;
1737949SAli.Saidi@ARM.com
1747949SAli.Saidi@ARM.com    int number;
1757949SAli.Saidi@ARM.com    int dataFd; // data stream file describer
1767949SAli.Saidi@ARM.com
1777949SAli.Saidi@ARM.com    ListenSocket listener;
1787949SAli.Saidi@ARM.com
1797949SAli.Saidi@ARM.com    void listen(int port);
1807949SAli.Saidi@ARM.com    void accept();
1817949SAli.Saidi@ARM.com    void data();
1827949SAli.Saidi@ARM.com    void detach();
1837949SAli.Saidi@ARM.com
1847949SAli.Saidi@ARM.com  public:
1857949SAli.Saidi@ARM.com    typedef VncServerParams Params;
1867949SAli.Saidi@ARM.com    VncServer(const Params *p);
1877949SAli.Saidi@ARM.com    ~VncServer();
1887949SAli.Saidi@ARM.com
1897949SAli.Saidi@ARM.com    // RFB
1907949SAli.Saidi@ARM.com  protected:
1917949SAli.Saidi@ARM.com
1927949SAli.Saidi@ARM.com    /** The rfb prototol state the connection is in */
1937949SAli.Saidi@ARM.com    ConnectionState curState;
1947949SAli.Saidi@ARM.com
1957949SAli.Saidi@ARM.com    /** An update needs to be sent to the client. Without doing this the
1967949SAli.Saidi@ARM.com     * client will constantly request data that is pointless */
1977949SAli.Saidi@ARM.com    bool sendUpdate;
1987949SAli.Saidi@ARM.com
1997949SAli.Saidi@ARM.com    /** The one and only pixel format we support */
2007949SAli.Saidi@ARM.com    PixelFormat pixelFormat;
2017949SAli.Saidi@ARM.com
2027949SAli.Saidi@ARM.com    /** If the vnc client supports receiving raw data. It always should */
2037949SAli.Saidi@ARM.com    bool supportsRawEnc;
2047949SAli.Saidi@ARM.com
2057949SAli.Saidi@ARM.com    /** If the vnc client supports the desktop resize command */
2067949SAli.Saidi@ARM.com    bool supportsResizeEnc;
2077949SAli.Saidi@ARM.com
2087949SAli.Saidi@ARM.com  protected:
2097949SAli.Saidi@ARM.com    /**
2107949SAli.Saidi@ARM.com     * vnc client Interface
2117949SAli.Saidi@ARM.com     */
2127949SAli.Saidi@ARM.com
2137949SAli.Saidi@ARM.com    /** Send an error message to the client
2147949SAli.Saidi@ARM.com     * @param error_msg text to send describing the error
2157949SAli.Saidi@ARM.com     */
2167949SAli.Saidi@ARM.com    void sendError(const char* error_msg);
2177949SAli.Saidi@ARM.com
2187949SAli.Saidi@ARM.com    /** Read some data from the client
2197949SAli.Saidi@ARM.com     * @param buf the data to read
2207949SAli.Saidi@ARM.com     * @param len the amount of data to read
2217949SAli.Saidi@ARM.com     * @return length read
2227949SAli.Saidi@ARM.com     */
2237949SAli.Saidi@ARM.com    size_t read(uint8_t *buf, size_t len);
2247949SAli.Saidi@ARM.com
2257949SAli.Saidi@ARM.com    /** Read len -1 bytes from the client into the buffer provided + 1
2267949SAli.Saidi@ARM.com     * assert that we read enough bytes. This function exists to handle
2277949SAli.Saidi@ARM.com     * reading all of the protocol structs above when we've already read
2287949SAli.Saidi@ARM.com     * the first byte which describes which one we're reading
2297949SAli.Saidi@ARM.com     * @param buf the address of the buffer to add one to and read data into
2307949SAli.Saidi@ARM.com     * @param len the amount of data  + 1 to read
2317949SAli.Saidi@ARM.com     * @return length read
2327949SAli.Saidi@ARM.com     */
2337949SAli.Saidi@ARM.com    size_t read1(uint8_t *buf, size_t len);
2347949SAli.Saidi@ARM.com
2357949SAli.Saidi@ARM.com
2367949SAli.Saidi@ARM.com    /** Templated version of the read function above to
2377949SAli.Saidi@ARM.com     * read simple data to the client
2387949SAli.Saidi@ARM.com     * @param val data to recv from the client
2397949SAli.Saidi@ARM.com     */
2407949SAli.Saidi@ARM.com    template <typename T> size_t read(T* val);
2417949SAli.Saidi@ARM.com
2427949SAli.Saidi@ARM.com
2437949SAli.Saidi@ARM.com    /** Write a buffer to the client.
2447949SAli.Saidi@ARM.com     * @param buf buffer to send
2457949SAli.Saidi@ARM.com     * @param len length of the buffer
2467949SAli.Saidi@ARM.com     * @return number of bytes sent
2477949SAli.Saidi@ARM.com     */
2487949SAli.Saidi@ARM.com    size_t write(const uint8_t *buf, size_t len);
2497949SAli.Saidi@ARM.com
2507949SAli.Saidi@ARM.com    /** Templated version of the write function above to
2517949SAli.Saidi@ARM.com     * write simple data to the client
2527949SAli.Saidi@ARM.com     * @param val data to send to the client
2537949SAli.Saidi@ARM.com     */
2547949SAli.Saidi@ARM.com    template <typename T> size_t write(T* val);
2557949SAli.Saidi@ARM.com
2567949SAli.Saidi@ARM.com    /** Send a string to the client
2577949SAli.Saidi@ARM.com     * @param str string to transmit
2587949SAli.Saidi@ARM.com     */
2597949SAli.Saidi@ARM.com    size_t write(const char* str);
2607949SAli.Saidi@ARM.com
2617949SAli.Saidi@ARM.com    /** Check the client's protocol verion for compatibility and send
2627949SAli.Saidi@ARM.com     * the security types we support
2637949SAli.Saidi@ARM.com     */
2647949SAli.Saidi@ARM.com    void checkProtocolVersion();
2657949SAli.Saidi@ARM.com
2667949SAli.Saidi@ARM.com    /** Check that the security exchange was successful
2677949SAli.Saidi@ARM.com     */
2687949SAli.Saidi@ARM.com    void checkSecurity();
2697949SAli.Saidi@ARM.com
2707949SAli.Saidi@ARM.com    /** Send client our idea about what the frame buffer looks like */
2717949SAli.Saidi@ARM.com    void sendServerInit();
2727949SAli.Saidi@ARM.com
2737949SAli.Saidi@ARM.com    /** Send an error message to the client when something goes wrong
2747949SAli.Saidi@ARM.com     * @param error_msg error to send
2757949SAli.Saidi@ARM.com     */
2767949SAli.Saidi@ARM.com    void sendError(std::string error_msg);
2777949SAli.Saidi@ARM.com
2787949SAli.Saidi@ARM.com    /** Send a updated frame buffer to the client.
2797949SAli.Saidi@ARM.com     * @todo this doesn't do anything smart and just sends the entire image
2807949SAli.Saidi@ARM.com     */
2817949SAli.Saidi@ARM.com    void sendFrameBufferUpdate();
2827949SAli.Saidi@ARM.com
2837949SAli.Saidi@ARM.com    /** Receive pixel foramt message from client and process it. */
2847949SAli.Saidi@ARM.com    void setPixelFormat();
2857949SAli.Saidi@ARM.com
2867949SAli.Saidi@ARM.com    /** Receive encodings message from client and process it. */
2877949SAli.Saidi@ARM.com    void setEncodings();
2887949SAli.Saidi@ARM.com
2897949SAli.Saidi@ARM.com    /** Receive message from client asking for updated frame buffer */
2907949SAli.Saidi@ARM.com    void requestFbUpdate();
2917949SAli.Saidi@ARM.com
2927949SAli.Saidi@ARM.com    /** Receive message from client providing new keyboard input */
2937949SAli.Saidi@ARM.com    void recvKeyboardInput();
2947949SAli.Saidi@ARM.com
2957949SAli.Saidi@ARM.com    /** Recv message from client providing new mouse movement or button click */
2967949SAli.Saidi@ARM.com    void recvPointerInput();
2977949SAli.Saidi@ARM.com
2987949SAli.Saidi@ARM.com    /**  Receive message from client that there is text in it's paste buffer.
2997949SAli.Saidi@ARM.com     * This is a no-op at the moment, but perhaps we would want to be able to
3007949SAli.Saidi@ARM.com     * paste it at some point.
3017949SAli.Saidi@ARM.com     */
3027949SAli.Saidi@ARM.com    void recvCutText();
3037949SAli.Saidi@ARM.com
3047949SAli.Saidi@ARM.com    /** Tell the client that the frame buffer resized. This happens when the
3057949SAli.Saidi@ARM.com     * simulated system changes video modes (E.g. X11 starts).
3067949SAli.Saidi@ARM.com     */
3077949SAli.Saidi@ARM.com    void sendFrameBufferResized();
3087949SAli.Saidi@ARM.com
3097949SAli.Saidi@ARM.com  public:
3107949SAli.Saidi@ARM.com    /** The frame buffer uses this call to notify the vnc server that
3117949SAli.Saidi@ARM.com     * the frame buffer has been updated and a new image needs to be sent to the
3127949SAli.Saidi@ARM.com     * client
3137949SAli.Saidi@ARM.com     */
3147949SAli.Saidi@ARM.com    void
3157949SAli.Saidi@ARM.com    setDirty()
3167949SAli.Saidi@ARM.com    {
3179330Schander.sudanthi@arm.com        VncInput::setDirty();
3187949SAli.Saidi@ARM.com        sendUpdate = true;
3197949SAli.Saidi@ARM.com        sendFrameBufferUpdate();
3207949SAli.Saidi@ARM.com    }
3217949SAli.Saidi@ARM.com
3227949SAli.Saidi@ARM.com    /** Set the mode of the data the frame buffer will be sending us
3237949SAli.Saidi@ARM.com     * @param mode the mode
3247949SAli.Saidi@ARM.com     */
3259330Schander.sudanthi@arm.com    void setFrameBufferParams(VideoConvert::Mode mode, uint16_t width,
3269330Schander.sudanthi@arm.com        uint16_t height);
3277949SAli.Saidi@ARM.com};
3287949SAli.Saidi@ARM.com
3297949SAli.Saidi@ARM.com#endif
330