/* * @file VNC.h * @date 11.05.2015 * @author Markus Sattler * * Copyright (c) 2015 Markus Sattler. All rights reserved. * This file is part of the VNC client for Arduino. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy can be downloaded from * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Thanks to all that worked on the original VNC implementation * */ #ifndef VNC_H_ #define VNC_H_ #include "VNC_config.h" /// more save free #define freeSec(ptr) \ free(ptr); \ ptr = 0 #include "Arduino.h" #ifdef VNC_ZRLE #if defined(ESP32) #include "esp32/rom/miniz.h" #else #include "miniz.h" #endif #endif // #ifdef VNC_ZRLE #ifdef USE_ARDUINO_TCP #if defined(ESP32) #include #elif defined(ESP8266) #include #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) #include #elif defined(RTL8722DM) #include #else // default platform #include #ifndef UIPETHERNET_H #include #include #endif // #ifndef UIPETHERNET_H #endif // default platform #endif // #ifdef USE_ARDUINO_TCP #define MAXPWLEN 8 #define CHALLENGESIZE 16 #define MAX_ENCODINGS 20 #ifdef WORDS_BIGENDIAN #define Swap16IfLE(s) (s) #define Swap32IfLE(l) (l) #else #define Swap16IfLE(s) __builtin_bswap16(s) #define Swap32IfLE(l) __builtin_bswap32(l) #endif /* WORDS_BIGENDIAN */ typedef uint8_t CARD8; typedef int8_t INT8; typedef uint16_t CARD16; typedef int16_t INT16; typedef uint32_t CARD32; typedef int32_t INT32; typedef struct serversettings { char *name; int width; int height; int bpp; int depth; int bigendian; int truecolour; int redmax; int greenmax; int bluemax; int redshift; int greenshift; int blueshift; } serversettings_t; typedef struct clientsettings { int width; int height; int bpp; int depth; int bigendian; int truecolour; int redmax; int greenmax; int bluemax; int redshift; int greenshift; int blueshift; int compresslevel; int quality; } clientsettings_t; //__dfb_vnc_options typedef struct { // char *servername; // int port; char *password; // char *passwordfile; // char *encodings; // char *modmapfile; serversettings_t server; clientsettings_t client; int shared; int stretch; int localcursor; // int poll_freq; /* not really options, but hey ;) */ double h_ratio; double v_ratio; int h_offset; int v_offset; } dfb_vnc_options; typedef struct { int x; int y; unsigned int buttonmask; } mousestate_t; #include "rfbproto.h" class VNCdisplay { protected: VNCdisplay() {} public: virtual ~VNCdisplay() {} virtual uint32_t getHeight(void) = 0; virtual uint32_t getWidth(void) = 0; virtual bool hasCopyRect(void) = 0; virtual void copy_rect(uint32_t src_x, uint32_t src_y, uint32_t dest_x, uint32_t dest_y, uint32_t w, uint32_t h){}; virtual void draw_area(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t *data) = 0; virtual void draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t color) = 0; virtual void flush() {}; virtual void vnc_options_override(dfb_vnc_options *opt){}; }; class arduinoVNC { public: arduinoVNC(VNCdisplay *display); ~arduinoVNC(void); void begin(char *host, uint16_t port = 5900, bool onlyFullUpdate = false); void begin(const char *host, uint16_t port = 5900, bool onlyFullUpdate = false); void begin(String host, uint16_t port = 5900, bool onlyFullUpdate = false); void setPassword(char *pass); void setPassword(const char *pass); void setPassword(String pass); bool connected(void); void reconnect(void); void loop(void); int forceFullUpdate(void); void mouseEvent(uint16_t x, uint16_t y, uint8_t buttonMask); void keyEvent(int key, int down_flag); private: bool onlyFullUpdate; int port; String host; String password; VNCdisplay *display; dfb_vnc_options opt; uint8_t protocolMinorVersion; int sock; mousestate_t mousestate; /// TCP handling void disconnect(void); bool read_from_rfb_server(int sock, char *out, size_t n); #ifdef VNC_ZRLE bool read_from_z(uint8_t *out, size_t n); #endif // #ifdef VNC_ZRLE bool write_exact(int sock, char *buf, size_t n); bool set_non_blocking(int sock); /// Connect to Server bool rfb_connect_to_server(const char *server, int display); bool rfb_initialise_connection(); bool _read_conn_failed_reason(void); bool _read_authentication_result(void); bool _rfb_negotiate_protocol(void); bool _rfb_authenticate(void); bool _rfb_initialise_client(void); bool _rfb_initialise_server(void); bool rfb_set_format_and_encodings(); bool rfb_set_desktop_size(); bool rfb_send_update_request(int incremental); bool rfb_set_continuous_updates(bool enable); bool rfb_handle_server_message(); bool rfb_update_mouse(); bool rfb_send_key_event(int key, int down_flag); // void rfb_get_rgb_from_data(int *r, int *g, int *b, char *data); /// Encode handling bool _handle_server_cut_text_message(rfbServerToClientMsg *msg); bool _handle_raw_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); bool _handle_raw_encoded_message_core(uint16_t x, uint16_t y, uint16_t w, uint16_t h); bool _handle_copyrect_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); #ifdef VNC_RRE bool _handle_rre_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif #ifdef VNC_CORRE bool _handle_corre_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif #ifdef VNC_HEXTILE bool _handle_hextile_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif #ifdef VNC_ZRLE bool _handle_zrle_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif bool _handle_cursor_pos_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); bool _handle_server_continuous_updates_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h); /// Encryption void vncRandomBytes(unsigned char *bytes); void vncEncryptBytes(unsigned char *bytes, char *passwd); #ifdef USE_ARDUINO_TCP #if defined(ESP32) WiFiClient TCPclient; #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) WiFiClient TCPclient; #elif defined(ESP8266) WiFiClient TCPclient; #elif defined(RTL8722DM) WiFiClient TCPclient; #else // default platform #ifdef UIPETHERNET_H UIPClient TCPclient; #else EthernetClient TCPclient; #endif #endif // default platform #endif // #ifdef USE_ARDUINO_TCP #ifdef TCP_BUFFER_SIZE uint8_t tcp_buffer[TCP_BUFFER_SIZE]; size_t buf_idx = 0; size_t buf_remain = 0; #endif uint32_t maxSize = VNC_RAW_BUFFER; char raw_buffer[VNC_RAW_BUFFER]; uint16_t framebuffer[FB_SIZE]; #ifdef VNC_ZRLE tinfl_decompressor inflator; bool header_inited = false; uint8_t *zin_buffer; size_t allocated_zin = 0, zin_buf_size = 0, zin_buf_ofs = 0; uint8_t *zdict; size_t zdict_ofs = 0; uint8_t *zout_buffer; size_t zout_buf_idx = 0, zout_buf_remain = 0; uint16_t palette[127]; #endif }; #endif /* MARKUS_VNC_H_ */