acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

VNC.cpp (52348B)

      1 /*
      2  * @file VNC.cpp
      3  * @date 11.05.2015
      4  * @author Markus Sattler
      5  *
      6  * Copyright (c) 2015 Markus Sattler. All rights reserved.
      7  * This file is part of the VNC client for Arduino.
      8  *
      9  * This program is free software; you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation; version 2 of the License
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, a copy can be downloaded from
     20  * http://www.gnu.org/licenses/gpl.html, or obtained by writing to the
     21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  *
     24  * Thanks to all that worked on the original VNC implementation
     25  *
     26  */
     27 
     28 #pragma GCC optimize("O2")
     29 
     30 #include <Arduino.h>
     31 
     32 #include <stdio.h>
     33 #include <unistd.h>
     34 #include <inttypes.h>
     35 #include <stdint.h>
     36 #include <math.h>
     37 
     38 #include "VNC.h"
     39 
     40 extern "C"
     41 {
     42 #include "d3des.h"
     43 }
     44 
     45 #ifndef min
     46 #define min(a, b) ((a) < (b) ? (a) : (b))
     47 #endif
     48 
     49 #ifdef FPS_BENCHMARK
     50 unsigned long connectionStart = 0;
     51 uint32_t frames = 0;
     52 size_t reads = 0;
     53 #endif
     54 
     55 //#############################################################################################
     56 
     57 arduinoVNC::arduinoVNC(VNCdisplay *_display)
     58 {
     59   host = "";
     60   port = 5900;
     61   display = _display;
     62   opt = {0};
     63   sock = 0;
     64   protocolMinorVersion = 3;
     65   onlyFullUpdate = false;
     66 }
     67 
     68 arduinoVNC::~arduinoVNC(void)
     69 {
     70   TCPclient.stop();
     71 }
     72 
     73 void arduinoVNC::begin(char *_host, uint16_t _port, bool _onlyFullUpdate)
     74 {
     75   host = _host;
     76   port = _port;
     77 
     78 #ifdef FPS_BENCHMARK
     79 #ifdef FPS_BENCHMARK_FULL
     80   onlyFullUpdate = true;
     81 #else
     82   onlyFullUpdate = false;
     83 #endif
     84 #else  // !FPS_BENCHMARK
     85   onlyFullUpdate = _onlyFullUpdate;
     86 #endif // !FPS_BENCHMARK
     87 
     88   opt.client.width = display->getWidth();
     89   opt.client.height = display->getHeight();
     90 
     91   opt.client.bpp = 16;
     92   opt.client.depth = 16;
     93 
     94   opt.client.bigendian = 0;
     95   opt.client.truecolour = 1;
     96 
     97   opt.client.redmax = 31;
     98   opt.client.greenmax = 63;
     99   opt.client.bluemax = 31;
    100 
    101   opt.client.redshift = 11;
    102   opt.client.greenshift = 5;
    103   opt.client.blueshift = 0;
    104 
    105 #ifdef VNC_COMPRESS_LEVEL
    106   opt.client.compresslevel = VNC_COMPRESS_LEVEL;
    107 #else
    108   opt.client.compresslevel = 99;
    109 #endif
    110   opt.client.quality = 99;
    111 
    112   opt.shared = 1;
    113   opt.localcursor = 1;
    114 
    115   opt.h_ratio = 1;
    116   opt.v_ratio = 1;
    117   opt.h_offset = 0;
    118   opt.v_offset = 0;
    119 
    120   display->vnc_options_override(&opt);
    121 }
    122 
    123 void arduinoVNC::begin(const char *_host, uint16_t _port, bool _onlyFullUpdate)
    124 {
    125   begin((char *)_host, _port, _onlyFullUpdate);
    126 }
    127 
    128 void arduinoVNC::begin(String _host, uint16_t _port, bool _onlyFullUpdate)
    129 {
    130   begin(_host.c_str(), _port, _onlyFullUpdate);
    131 }
    132 
    133 void arduinoVNC::setPassword(char *pass)
    134 {
    135   password = pass;
    136   opt.password = (char *)password.c_str();
    137 }
    138 
    139 void arduinoVNC::setPassword(const char *pass)
    140 {
    141   password = pass;
    142   opt.password = (char *)password.c_str();
    143 }
    144 
    145 void arduinoVNC::setPassword(String pass)
    146 {
    147   password = pass;
    148   opt.password = (char *)password.c_str();
    149 }
    150 
    151 void arduinoVNC::loop(void)
    152 {
    153   static uint16_t fails = 0;
    154   static unsigned long lastUpdate = 0;
    155 
    156 #ifdef ESP8266
    157   if (WiFi.status() != WL_CONNECTED)
    158   {
    159     if (connected())
    160     {
    161       disconnect();
    162     }
    163     return;
    164   }
    165 #endif
    166 
    167   if (!connected())
    168   {
    169     DEBUG_VNC("!connected\n");
    170     if (!rfb_connect_to_server(host.c_str(), port))
    171     {
    172       DEBUG_VNC("Couldnt establish connection with the VNC server. Exiting\n");
    173       delay(2000);
    174       return;
    175     }
    176 
    177     /* initialize the connection */
    178     if (!rfb_initialise_connection())
    179     {
    180       DEBUG_VNC("Connection with VNC server couldnt be initialized. Exiting\n");
    181       disconnect();
    182       delay(2000);
    183       return;
    184     }
    185 
    186     /* Tell the VNC server which pixel format and encodings we want to use */
    187     if (!rfb_set_format_and_encodings())
    188     {
    189       DEBUG_VNC("Error negotiating format and encodings. Exiting.\n");
    190       disconnect();
    191       delay(2000);
    192       return;
    193     }
    194 
    195 #ifdef SET_DESKTOP_SIZE
    196     /* set display resolution */
    197     if (!rfb_set_desktop_size())
    198     {
    199       DEBUG_VNC("Error set desktop size. Exiting.\n");
    200       disconnect();
    201       delay(2000);
    202       return;
    203     }
    204 #endif
    205 
    206     /* calculate horizontal and vertical offset */
    207     if (opt.client.width > opt.server.width)
    208     {
    209       opt.h_offset = rint((opt.client.width - opt.server.width) / 2);
    210     }
    211     if (opt.client.height > opt.server.height)
    212     {
    213       opt.v_offset = rint((opt.client.height - opt.server.height) / 2);
    214     }
    215 
    216     mousestate.x = opt.client.width / 2;
    217     mousestate.y = opt.client.height / 2;
    218 
    219     // no scale support for embedded systems!
    220     opt.h_ratio = 1; //(double) opt.client.width / (double) opt.server.width;
    221     opt.v_ratio = 1; //(double) opt.client.height / (double) opt.server.height;
    222 
    223     rfb_send_update_request(0);
    224     // rfb_set_continuous_updates(1);
    225 
    226     DEBUG_VNC("vnc_connect Done.\n");
    227 #ifdef FPS_BENCHMARK
    228     connectionStart = millis();
    229     frames = 0;
    230 #endif
    231 #ifdef VNC_ZRLE
    232     if (!zdict)
    233     {
    234       zdict = (uint8_t *)malloc(TDEFL_LZ_DICT_SIZE);
    235     }
    236     if (!zdict)
    237     {
    238       DEBUG_VNC("zdict malloc failed!\n");
    239     }
    240     if (!zout_buffer)
    241     {
    242       zout_buffer = (uint8_t *)malloc(TDEFL_LZ_DICT_SIZE);
    243     }
    244     if (!zout_buffer)
    245     {
    246       DEBUG_VNC("zout_buffer malloc failed!\n");
    247     }
    248 
    249     tinfl_init(&inflator);
    250     // reset dict
    251     memset(zdict, 0, TINFL_LZ_DICT_SIZE);
    252     zdict_ofs = 0;
    253 #endif // #ifdef VNC_ZRLE
    254   }
    255   else
    256   {
    257     if (!rfb_handle_server_message())
    258     {
    259       DEBUG_VNC("rfb_handle_server_message faild.\n");
    260       return;
    261     }
    262 
    263 #ifdef MAXFPS
    264     unsigned long currentMs = millis();
    265     if ((currentMs - lastUpdate) > (1000 / MAXFPS))
    266     {
    267       if (rfb_send_update_request(onlyFullUpdate ? 0 : 1))
    268       {
    269         lastUpdate = currentMs;
    270         fails = 0;
    271       }
    272       else
    273       {
    274         fails++;
    275         if (fails > 20)
    276         {
    277           disconnect();
    278         }
    279       }
    280     }
    281 #else
    282     if (rfb_send_update_request(onlyFullUpdate ? 0 : 1))
    283     {
    284       fails = 0;
    285     }
    286     else
    287     {
    288       fails++;
    289       if (fails > 20)
    290       {
    291         disconnect();
    292       }
    293     }
    294 #endif
    295   }
    296 #ifdef SLOW_LOOP
    297   delay(SLOW_LOOP);
    298 #endif
    299 }
    300 
    301 int arduinoVNC::forceFullUpdate(void)
    302 {
    303   return rfb_send_update_request(1);
    304 }
    305 
    306 void arduinoVNC::mouseEvent(uint16_t x, uint16_t y, uint8_t buttonMask)
    307 {
    308   mousestate.x = x;
    309   mousestate.y = y;
    310   mousestate.buttonmask = buttonMask;
    311   rfb_update_mouse();
    312 }
    313 
    314 void arduinoVNC::keyEvent(int key, int down_flag)
    315 {
    316   rfb_send_key_event(key, down_flag);
    317 }
    318 
    319 void arduinoVNC::reconnect(void)
    320 {
    321   // auto reconnect on next loop
    322   disconnect();
    323 }
    324 
    325 bool arduinoVNC::connected(void)
    326 {
    327 #ifdef ESP8266
    328   return (TCPclient.status() == ESTABLISHED);
    329 #else
    330   return TCPclient.connected();
    331 #endif
    332 }
    333 
    334 //#############################################################################################
    335 //                                       TCP handling
    336 //#############################################################################################
    337 
    338 #ifdef USE_ARDUINO_TCP
    339 
    340 bool arduinoVNC::read_from_rfb_server(int sock, char *out, size_t n)
    341 {
    342 #ifdef FPS_BENCHMARK
    343   reads += n;
    344 #endif
    345 
    346   unsigned long t = millis();
    347   size_t len;
    348   /*
    349    DEBUG_VNC("read_from_rfb_server %d...\n", n);
    350 
    351    if(n > 2 * 1024 * 1042) {
    352    DEBUG_VNC("read_from_rfb_server N: %d 0x%08X make no sens!\n", n, n);
    353    return 0;
    354    }
    355 
    356    if(out == NULL) {
    357    DEBUG_VNC("read_from_rfb_server out == NULL!\n");
    358    return 0;
    359    }
    360    */
    361 #ifdef TCP_BUFFER_SIZE
    362   if (n > TCP_BUFFER_SIZE)
    363   {
    364     if (buf_remain > 0)
    365     {
    366       memcpy(out, tcp_buffer + buf_idx, buf_remain);
    367       n -= buf_remain;
    368       out += buf_remain;
    369       buf_idx = 0;
    370       buf_remain = 0;
    371     }
    372 #endif // #ifdef TCP_BUFFER_SIZE
    373     while (n > 0)
    374     {
    375       if (!connected())
    376       {
    377         DEBUG_VNC("[read_from_rfb_server] not connected!\n");
    378         return false;
    379       }
    380 
    381       if ((millis() - t) > VNC_TCP_TIMEOUT)
    382       {
    383         DEBUG_VNC("[read_from_rfb_server] receive TIMEOUT!\n");
    384         return false;
    385       }
    386 
    387       if (!TCPclient.available())
    388       {
    389         delay(0);
    390         continue;
    391       }
    392 
    393       len = TCPclient.read((uint8_t *)out, n);
    394       if (len)
    395       {
    396         t = millis();
    397         out += len;
    398         n -= len;
    399         // DEBUG_VNC("Receive %d left %d!\n", len, n);
    400       }
    401       else
    402       {
    403         // DEBUG_VNC("Receive %d left %d!\n", len, n);
    404       }
    405       delay(0);
    406     }
    407 #ifdef TCP_BUFFER_SIZE
    408   }
    409   else
    410   {
    411     while (buf_remain < n)
    412     {
    413       if (!connected())
    414       {
    415         DEBUG_VNC("[read_from_rfb_server] not connected!\n");
    416         return false;
    417       }
    418 
    419       if ((millis() - t) > VNC_TCP_TIMEOUT)
    420       {
    421         DEBUG_VNC("[read_from_rfb_server] receive TIMEOUT!\n");
    422         return false;
    423       }
    424 
    425       if (!TCPclient.available())
    426       {
    427         delay(0);
    428         continue;
    429       }
    430 
    431       if (buf_remain > 0)
    432       {
    433         if (buf_idx > 0)
    434         {
    435           memcpy(tcp_buffer, tcp_buffer + buf_idx, buf_remain);
    436           buf_idx = 0;
    437         }
    438       }
    439       else
    440       {
    441         buf_idx = 0;
    442       }
    443 
    444       len = TCPclient.read(tcp_buffer + buf_remain, TCP_BUFFER_SIZE - buf_remain);
    445       // DEBUG_VNC("[read_from_rfb_server] require: %d, receive: %d, buf_idx: %d, buf_remain: %d!\n", n, len, buf_idx, buf_remain);
    446       buf_remain += len;
    447       t = millis();
    448       delay(0);
    449     }
    450 
    451     // DEBUG_VNC("[read_from_rfb_server] memcpy, n: %d, buf_idx: %d, buf_remain: %d!\n", n, buf_idx, buf_remain);
    452     memcpy(out, tcp_buffer + buf_idx, n);
    453     buf_idx += n;
    454     buf_remain -= n;
    455   }
    456 #endif // #ifdef TCP_BUFFER_SIZE
    457   return true;
    458 }
    459 
    460 #ifdef VNC_ZRLE
    461 bool arduinoVNC::read_from_z(uint8_t *out, size_t n)
    462 {
    463   while (zout_buf_remain < n)
    464   {
    465     if (zout_buf_remain > 0)
    466     {
    467       if (zout_buf_idx > 0)
    468       {
    469         memcpy(out, zout_buffer + zout_buf_idx, zout_buf_remain);
    470         n -= zout_buf_remain;
    471         out += zout_buf_remain;
    472         zout_buf_remain = 0;
    473         zout_buf_idx = 0;
    474       }
    475     }
    476     else
    477     {
    478       zout_buf_idx = 0;
    479     }
    480 
    481     int flag = TINFL_FLAG_HAS_MORE_INPUT;
    482     if (!header_inited)
    483     {
    484       flag |= TINFL_FLAG_PARSE_ZLIB_HEADER;
    485       header_inited = true;
    486     }
    487 
    488     size_t in_buf_size = zin_buf_size - zin_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - zdict_ofs;
    489     tinfl_decompress(&inflator, (const mz_uint8 *)zin_buffer + zin_buf_ofs, &in_buf_size, zdict, zdict + zdict_ofs, &dst_buf_size, flag);
    490     zin_buf_ofs += in_buf_size;
    491     memcpy(zout_buffer + zout_buf_idx, zdict + zdict_ofs, dst_buf_size);
    492 
    493     zdict_ofs = (zdict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
    494 
    495     zout_buf_remain += dst_buf_size;
    496     // DEBUG_VNC("[read_from_z] zin_buf_size: %d, zin_buf_ofs: %d, n: %d, zout_buf_idx: %d, zout_buf_remain: %d!\n", zin_buf_size, zin_buf_ofs, n, zout_buf_idx, zout_buf_remain);
    497   }
    498 
    499   memcpy(out, zout_buffer + zout_buf_idx, n);
    500   zout_buf_idx += n;
    501   zout_buf_remain -= n;
    502 
    503   return true;
    504 }
    505 #endif // #ifdef VNC_ZRLE
    506 
    507 bool arduinoVNC::write_exact(int sock, char *buf, size_t n)
    508 {
    509   if (!connected())
    510   {
    511     DEBUG_VNC("[write_exact] not connected!\n");
    512     return false;
    513   }
    514   return (TCPclient.write((uint8_t *)buf, n) == n);
    515 }
    516 
    517 bool arduinoVNC::set_non_blocking(int sock)
    518 {
    519 #ifdef ESP8266
    520   TCPclient.setNoDelay(true);
    521 #endif
    522   return true;
    523 }
    524 
    525 void arduinoVNC::disconnect(void)
    526 {
    527   DEBUG_VNC("[arduinoVNC] disconnect...\n");
    528   TCPclient.stop();
    529 }
    530 
    531 #else // !USE_ARDUINO_TCP
    532 #error implement TCP handling
    533 #endif // !USE_ARDUINO_TCP
    534 
    535 //#############################################################################################
    536 //                                       Connect to Server
    537 //#############################################################################################
    538 /*
    539  * ConnectToRFBServer.
    540  */
    541 bool arduinoVNC::rfb_connect_to_server(const char *host, int port)
    542 {
    543 #ifdef USE_ARDUINO_TCP
    544   if (!TCPclient.connect(host, port))
    545   {
    546     DEBUG_VNC("[rfb_connect_to_server] Connect error\n");
    547     return false;
    548   }
    549 
    550   DEBUG_VNC("[rfb_connect_to_server] Connected.\n");
    551   set_non_blocking(sock);
    552   return true;
    553 #else  // !USE_ARDUINO_TCP
    554   struct hostent *he = NULL;
    555   int one = 1;
    556   struct sockaddr_in s;
    557 
    558   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    559   {
    560     DEBUG_VNC("Error creating communication socket: %d\n", errno);
    561     // exit(2)
    562     return false;
    563   }
    564 
    565   /* if the server wasnt specified as an ip address, look it up */
    566   if (!inet_aton(host, &s.sin_addr))
    567   {
    568     if ((he = gethostbyname(host)))
    569       memcpy(&s.sin_addr.s_addr, he->h_addr, he->h_length);
    570     else
    571     {
    572       DEBUG_VNC("Couldnt resolve host!\n");
    573       close(sock);
    574       return false;
    575     }
    576   }
    577 
    578   s.sin_port = htons(port);
    579   s.sin_family = AF_INET;
    580 
    581   if (connect(sock, (struct sockaddr *)&s, sizeof(s)) < 0)
    582   {
    583     DEBUG_VNC("Connect error\n");
    584     close(sock);
    585     return false;
    586   }
    587   if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0)
    588   {
    589     DEBUG_VNC("Error setting socket options\n");
    590     close(sock);
    591     return false;
    592   }
    593 
    594   if (!set_non_blocking(sock))
    595     return -1;
    596 
    597   return (sock);
    598 #endif // !USE_ARDUINO_TCP
    599 }
    600 
    601 bool arduinoVNC::rfb_initialise_connection()
    602 {
    603   if (!_rfb_negotiate_protocol())
    604   {
    605     DEBUG_VNC("[rfb_initialise_connection] _rfb_negotiate_protocol()  Faild!\n");
    606     return false;
    607   }
    608 
    609   if (!_rfb_authenticate())
    610   {
    611     DEBUG_VNC("[rfb_initialise_connection] _rfb_authenticate()  Faild!\n");
    612     return false;
    613   }
    614 
    615   if (!_rfb_initialise_client())
    616   {
    617     DEBUG_VNC("[rfb_initialise_connection] _rfb_initialise_client()  Faild!\n");
    618     return false;
    619   }
    620 
    621   if (!_rfb_initialise_server())
    622   {
    623     DEBUG_VNC("[rfb_initialise_connection] _rfb_initialise_server() Faild!\n");
    624     return false;
    625   }
    626 
    627   return true;
    628 }
    629 
    630 bool arduinoVNC::_rfb_negotiate_protocol()
    631 {
    632   uint16_t server_major, server_minor;
    633 
    634   rfbProtocolVersionMsg msg;
    635 
    636   /* read the protocol version the server uses */
    637   if (!read_from_rfb_server(sock, (char *)&msg, sz_rfbProtocolVersionMsg))
    638     return false;
    639 
    640   // RFB xxx.yyy
    641   if (msg[0] != 'R' || msg[1] != 'F' || msg[2] != 'B' || msg[3] != ' ' || msg[7] != '.')
    642   {
    643     DEBUG_VNC("[_rfb_negotiate_protocol] Not a valid VNC server\n");
    644     return false;
    645   }
    646   msg[11] = 0x00;
    647 
    648   DEBUG_VNC("[_rfb_negotiate_protocol] Server protocol: %s\n", msg);
    649 
    650   char majorStr[4]{msg[4], msg[5], msg[6], 0x00};
    651   char minorStr[4]{msg[8], msg[9], msg[10], 0x00};
    652 
    653   server_major = atol((const char *)&majorStr);
    654   server_minor = atol((const char *)&minorStr);
    655 
    656   if (server_major == 3 && server_minor >= 8)
    657   {
    658     /* the server supports protocol 3.8 or higher version */
    659     protocolMinorVersion = 8;
    660   }
    661   else if (server_major == 3 && server_minor == 7)
    662   {
    663     /* the server supports protocol 3.7 */
    664     protocolMinorVersion = 7;
    665   }
    666   else
    667   {
    668     /* any other server version, request the standard 3.3 */
    669     protocolMinorVersion = 3;
    670   }
    671 
    672   /* send the protocol version we want to use */
    673   sprintf(msg, rfbProtocolVersionFormat, rfbProtocolMajorVersion, protocolMinorVersion);
    674 
    675   DEBUG_VNC("[_rfb_negotiate_protocol] used protocol: %s\n", msg);
    676 
    677   if (!write_exact(sock, msg, sz_rfbProtocolVersionMsg))
    678   {
    679     return false;
    680   }
    681 
    682   return true;
    683 }
    684 
    685 bool arduinoVNC::_read_conn_failed_reason(void)
    686 {
    687   CARD32 reason_length;
    688   CARD8 *reason_string;
    689   DEBUG_VNC("[_read_conn_failed_reason] Connection to VNC server failed\n");
    690 
    691   if (!read_from_rfb_server(sock, (char *)&reason_length, sizeof(CARD32)))
    692   {
    693     return false;
    694   }
    695 
    696   reason_length = Swap32IfLE(reason_length);
    697   reason_string = (CARD8 *)malloc(sizeof(CARD8) * reason_length);
    698 
    699   if (!reason_string)
    700   {
    701     return false;
    702   }
    703 
    704   if (!read_from_rfb_server(sock, (char *)reason_string, reason_length))
    705   {
    706     freeSec(reason_string);
    707     return false;
    708   }
    709 
    710   DEBUG_VNC("[_read_conn_failed_reason] Errormessage: %s\n", reason_string);
    711   freeSec(reason_string);
    712   return true;
    713 }
    714 
    715 bool arduinoVNC::_read_authentication_result(void)
    716 {
    717   CARD32 auth_result;
    718   if (!read_from_rfb_server(sock, (char *)&auth_result, 4))
    719   {
    720     return false;
    721   }
    722 
    723   auth_result = Swap32IfLE(auth_result);
    724   switch (auth_result)
    725   {
    726   case rfbAuthFailed:
    727     DEBUG_VNC("Authentication Failed\n");
    728     return false;
    729   case rfbAuthTooMany:
    730     DEBUG_VNC("Too many connections\n");
    731     return false;
    732   case rfbAuthOK:
    733     DEBUG_VNC("Authentication OK\n");
    734     return true;
    735   default:
    736     DEBUG_VNC("Unknown result of authentication: 0x%08X (%d)\n", auth_result, auth_result);
    737     return false;
    738   }
    739 }
    740 
    741 bool arduinoVNC::_rfb_authenticate()
    742 {
    743   CARD32 authscheme;
    744   CARD8 challenge_and_response[CHALLENGESIZE];
    745 
    746   if (protocolMinorVersion >= 7)
    747   {
    748     CARD8 secType = rfbSecTypeInvalid;
    749 
    750     CARD8 nSecTypes;
    751     CARD8 *secTypes;
    752 
    753     CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
    754     uint8_t nKnownSecTypes = sizeof(knownSecTypes);
    755 
    756     if (!read_from_rfb_server(sock, (char *)&nSecTypes, sizeof(nSecTypes)))
    757     {
    758       return false;
    759     }
    760 
    761     if (nSecTypes == 0)
    762     {
    763       if (!_read_conn_failed_reason())
    764       {
    765         return false;
    766       }
    767     }
    768 
    769     secTypes = (CARD8 *)malloc(nSecTypes);
    770 
    771     if (!secTypes)
    772     {
    773       return false;
    774     }
    775 
    776     if (!read_from_rfb_server(sock, (char *)secTypes, nSecTypes))
    777     {
    778       freeSec(secTypes);
    779       return false;
    780     }
    781     if (secType == rfbSecTypeInvalid)
    782     {
    783       // use first supported security type
    784       for (uint8_t x = 0; x < nSecTypes; x++)
    785       {
    786         for (uint8_t i = 0; i < nKnownSecTypes; i++)
    787         {
    788           if (secTypes[x] == knownSecTypes[i])
    789           {
    790             secType = secTypes[x];
    791             break;
    792           }
    793         }
    794         if (secType != rfbSecTypeInvalid)
    795         {
    796           break;
    797         }
    798       }
    799     }
    800 
    801     freeSec(secTypes);
    802 
    803     if (!write_exact(sock, (char *)&secType, sizeof(secType)))
    804     {
    805       return false;
    806     }
    807 
    808     if (secType == rfbSecTypeInvalid)
    809     {
    810       DEBUG_VNC("Server did not offer supported security type\n");
    811     }
    812 
    813     authscheme = secType;
    814   }
    815   else
    816   {
    817     // protocol Minor < 7
    818     if (!read_from_rfb_server(sock, (char *)&authscheme, 4))
    819     {
    820       return false;
    821     }
    822     authscheme = Swap32IfLE(authscheme);
    823     if (authscheme == rfbSecTypeInvalid)
    824     {
    825       if (!_read_conn_failed_reason())
    826       {
    827         return false;
    828       }
    829     }
    830   }
    831 
    832   switch (authscheme)
    833   {
    834   case rfbSecTypeInvalid:
    835     return false;
    836     break;
    837   case rfbSecTypeNone:
    838     if (protocolMinorVersion >= 8)
    839     {
    840       return _read_authentication_result();
    841     }
    842     return true;
    843     break;
    844   case rfbSecTypeTight:
    845     return false;
    846     break;
    847   case rfbSecTypeVncAuth:
    848 
    849     if (!opt.password || *(opt.password) == 0x00)
    850     {
    851       DEBUG_VNC("Server ask for password? but no Password is set.\n");
    852       return false;
    853     }
    854 
    855     if (!read_from_rfb_server(sock, (char *)challenge_and_response, CHALLENGESIZE))
    856     {
    857       return false;
    858     }
    859 
    860     vncEncryptBytes(challenge_and_response, opt.password);
    861     if (!write_exact(sock, (char *)challenge_and_response, CHALLENGESIZE))
    862     {
    863       return false;
    864     }
    865     return _read_authentication_result();
    866     break;
    867   }
    868 
    869   return false;
    870 }
    871 
    872 bool arduinoVNC::_rfb_initialise_client()
    873 {
    874   rfbClientInitMsg cl;
    875   cl.shared = opt.shared;
    876   if (!write_exact(sock, (char *)&cl, sz_rfbClientInitMsg))
    877   {
    878     return false;
    879   }
    880 
    881   return true;
    882 }
    883 
    884 bool arduinoVNC::_rfb_initialise_server()
    885 {
    886   int len;
    887   rfbServerInitMsg si;
    888 
    889   if (!read_from_rfb_server(sock, (char *)&si, sz_rfbServerInitMsg))
    890   {
    891     return false;
    892   }
    893 
    894   opt.server.width = Swap16IfLE(si.framebufferWidth);
    895   opt.server.height = Swap16IfLE(si.framebufferHeight);
    896 
    897   // never be bigger then the client!
    898   opt.server.width = min(opt.client.width, opt.server.width);
    899   opt.server.height = min(opt.client.height, opt.server.height);
    900 
    901   opt.server.bpp = si.format.bitsPerPixel;
    902   opt.server.depth = si.format.depth;
    903   opt.server.bigendian = si.format.bigEndian;
    904   opt.server.truecolour = si.format.trueColour;
    905 
    906   opt.server.redmax = Swap16IfLE(si.format.redMax);
    907   opt.server.greenmax = Swap16IfLE(si.format.greenMax);
    908   opt.server.bluemax = Swap16IfLE(si.format.blueMax);
    909   opt.server.redshift = si.format.redShift;
    910   opt.server.greenshift = si.format.greenShift;
    911   opt.server.blueshift = si.format.blueShift;
    912 
    913   len = Swap32IfLE(si.nameLength);
    914   opt.server.name = (char *)malloc(sizeof(char) * len + 1);
    915 
    916   if (!read_from_rfb_server(sock, opt.server.name, len))
    917   {
    918     return false;
    919   }
    920   opt.server.name[len] = 0x00;
    921 
    922   DEBUG_VNC("[VNC-SERVER] VNC Server config - Name: %s\n", opt.server.name);
    923   DEBUG_VNC(" - width:%d      height:%d\n", Swap16IfLE(si.framebufferWidth), Swap16IfLE(si.framebufferHeight));
    924   DEBUG_VNC(" - bpp:%d        depth:%d       bigendian:%d     truecolor:%d\n", opt.server.bpp, opt.server.depth, opt.server.bigendian, opt.server.truecolour);
    925   DEBUG_VNC(" - redmax:%d     greenmax:%d    bluemax:%d\n", opt.server.redmax, opt.server.greenmax, opt.server.bluemax);
    926   DEBUG_VNC(" - redshift:%d   greenshift:%d  blueshift:%d\n", opt.server.redshift, opt.server.greenshift, opt.server.blueshift);
    927   return true;
    928 }
    929 
    930 //#############################################################################################
    931 //                                      Connection handling
    932 //#############################################################################################
    933 
    934 bool arduinoVNC::rfb_set_format_and_encodings()
    935 {
    936   uint8_t num_enc = 0;
    937   rfbSetPixelFormatMsg pf;
    938   rfbSetEncodingsMsg em;
    939   CARD32 enc[MAX_ENCODINGS];
    940 
    941   pf.type = rfbSetPixelFormat;
    942   pf.format.bitsPerPixel = opt.client.bpp;
    943   pf.format.depth = opt.client.depth;
    944   pf.format.bigEndian = opt.client.bigendian;
    945   pf.format.trueColour = opt.client.truecolour;
    946   pf.format.redMax = Swap16IfLE(opt.client.redmax);
    947   pf.format.greenMax = Swap16IfLE(opt.client.greenmax);
    948   pf.format.blueMax = Swap16IfLE(opt.client.bluemax);
    949   pf.format.redShift = opt.client.redshift;
    950   pf.format.greenShift = opt.client.greenshift;
    951   pf.format.blueShift = opt.client.blueshift;
    952 
    953   if (!write_exact(sock, (char *)&pf, sz_rfbSetPixelFormatMsg))
    954   {
    955     return false;
    956   }
    957 
    958   em.type = rfbSetEncodings;
    959 
    960   DEBUG_VNC("[VNC-CLIENT] Supported Encodings:\n");
    961 #ifdef VNC_ZRLE
    962   enc[num_enc++] = Swap32IfLE(rfbEncodingZRLE);
    963   DEBUG_VNC(" - ZRLE\n");
    964 #endif
    965 #ifdef VNC_HEXTILE
    966   enc[num_enc++] = Swap32IfLE(rfbEncodingHextile);
    967   DEBUG_VNC(" - Hextile\n");
    968 #endif
    969 
    970   if (display->hasCopyRect())
    971   {
    972     enc[num_enc++] = Swap32IfLE(rfbEncodingCopyRect);
    973     DEBUG_VNC(" - CopyRect\n");
    974   }
    975 
    976 #ifdef VNC_RRE
    977   enc[num_enc++] = Swap32IfLE(rfbEncodingRRE);
    978   DEBUG_VNC(" - RRE\n");
    979 #endif
    980 #ifdef VNC_CORRE
    981   enc[num_enc++] = Swap32IfLE(rfbEncodingCoRRE);
    982   DEBUG_VNC(" - CoRRE\n");
    983 #endif
    984 
    985   enc[num_enc++] = Swap32IfLE(rfbEncodingRaw);
    986   DEBUG_VNC(" - Raw\n");
    987 
    988   DEBUG_VNC("[VNC-CLIENT] Supported Special Encodings:\n");
    989 
    990 #ifdef SET_DESKTOP_SIZE
    991   enc[num_enc++] = Swap32IfLE(rfbEncodingNewFBSize);
    992   DEBUG_VNC(" - SetDesktopSize\n");
    993 #endif
    994 
    995   enc[num_enc++] = Swap32IfLE(rfbEncodingPointerPos);
    996   DEBUG_VNC(" - CursorPos\n");
    997 
    998   // enc[num_enc++] = Swap32IfLE(rfbEncodingLastRect);
    999   // DEBUG_VNC(" - LastRect\n");
   1000 
   1001   enc[num_enc++] = Swap32IfLE(rfbEncodingContinuousUpdates);
   1002   DEBUG_VNC(" - ContinuousUpdates\n");
   1003 
   1004   if (opt.client.compresslevel <= 9)
   1005   {
   1006     enc[num_enc++] = Swap32IfLE(rfbEncodingCompressLevel0 + opt.client.compresslevel);
   1007     DEBUG_VNC(" - compresslevel: %d\n", opt.client.compresslevel);
   1008   }
   1009   if (opt.client.quality <= 9)
   1010   {
   1011     enc[num_enc++] = Swap32IfLE(rfbEncodingQualityLevel0 + opt.client.quality);
   1012     DEBUG_VNC(" - quality: %d\n", opt.client.quality);
   1013   }
   1014 
   1015   em.nEncodings = Swap16IfLE(num_enc);
   1016 
   1017   if (!write_exact(sock, (char *)&em, sz_rfbSetEncodingsMsg))
   1018   {
   1019     return false;
   1020   }
   1021 
   1022   if (!write_exact(sock, (char *)&enc, num_enc * 4))
   1023   {
   1024     return false;
   1025   }
   1026 
   1027   DEBUG_VNC("[VNC-CLIENT] Client pixel format:\n");
   1028   DEBUG_VNC(" - width:%d      height:%d\n", opt.client.width, opt.client.height);
   1029   DEBUG_VNC(" - bpp:%d        depth:%d        bigEndian:%d    trueColor:%d\n", opt.client.bpp, opt.client.depth, opt.client.bigendian, opt.client.truecolour);
   1030   DEBUG_VNC(" - red-max:%d    green-max:%d    blue-max:%d\n", opt.client.redmax, opt.client.greenmax, opt.client.bluemax);
   1031   DEBUG_VNC(" - red-shift:%d  green-shift:%d  blue-shift:%d\n", opt.client.redshift, opt.client.greenshift, opt.client.blueshift);
   1032 
   1033   return true;
   1034 }
   1035 
   1036 #ifdef SET_DESKTOP_SIZE
   1037 bool arduinoVNC::rfb_set_desktop_size()
   1038 {
   1039   uint16_t w = opt.client.width;
   1040   uint16_t h = opt.client.height;
   1041 
   1042   // override server resolution
   1043   opt.server.width = w;
   1044   opt.server.height = h;
   1045 
   1046   w = Swap16IfLE(w);
   1047   h = Swap16IfLE(h);
   1048   rfbSetDesktopSizeMsg ds;
   1049   ds.type = rfbSetDesktopSize;
   1050   ds.pad1 = 0;
   1051   ds.width = w;
   1052   ds.height = h;
   1053   ds.numScreens = 1;
   1054   ds.pad2 = 0;
   1055   ds.layoutId = 1;
   1056   ds.layoutX = 0;
   1057   ds.layoutY = 0;
   1058   ds.layoutWidth = w;
   1059   ds.layoutHeight = h;
   1060   ds.layoutFlag = 0;
   1061 
   1062   if (!write_exact(sock, (char *)&ds, sz_rfbSetDesktopSizeMsg))
   1063   {
   1064     return false;
   1065   }
   1066 
   1067   return true;
   1068 }
   1069 #endif
   1070 
   1071 bool arduinoVNC::rfb_send_update_request(int incremental)
   1072 {
   1073   rfbFramebufferUpdateRequestMsg urq = {0};
   1074 
   1075   urq.type = rfbFramebufferUpdateRequest;
   1076   urq.incremental = incremental;
   1077   urq.x = 0;
   1078   urq.y = 0;
   1079   urq.w = opt.server.width;
   1080   urq.h = opt.server.height;
   1081 
   1082   urq.x = Swap16IfLE(urq.x);
   1083   urq.y = Swap16IfLE(urq.y);
   1084   urq.w = Swap16IfLE(urq.w);
   1085   urq.h = Swap16IfLE(urq.h);
   1086 
   1087   if (!write_exact(sock, (char *)&urq, sz_rfbFramebufferUpdateRequestMsg))
   1088   {
   1089     DEBUG_VNC("[rfb_send_update_request] write_exact failed!\n");
   1090     return false;
   1091   }
   1092 
   1093   return true;
   1094 }
   1095 
   1096 bool arduinoVNC::rfb_set_continuous_updates(bool enable)
   1097 {
   1098   rfbEnableContinuousUpdatesMsg urq = {0};
   1099 
   1100   urq.type = rfbEnableContinuousUpdates;
   1101   urq.enable = enable;
   1102   urq.x = 0;
   1103   urq.y = 0;
   1104   urq.w = opt.server.width;
   1105   urq.h = opt.server.height;
   1106 
   1107   urq.x = Swap16IfLE(urq.x);
   1108   urq.y = Swap16IfLE(urq.y);
   1109   urq.w = Swap16IfLE(urq.w);
   1110   urq.h = Swap16IfLE(urq.h);
   1111 
   1112   if (!write_exact(sock, (char *)&urq, sz_rfbEnableContinuousUpdatesMsg))
   1113   {
   1114     DEBUG_VNC("[rfb_set_continuous_updates] write_exact failed!\n");
   1115     return false;
   1116   }
   1117 
   1118   return true;
   1119 }
   1120 
   1121 bool arduinoVNC::rfb_handle_server_message()
   1122 {
   1123   rfbServerToClientMsg msg = {0};
   1124   rfbFramebufferUpdateRectHeader rectheader = {0};
   1125 
   1126   if (TCPclient.available())
   1127   {
   1128     if (!read_from_rfb_server(sock, (char *)&msg, 1))
   1129     {
   1130       return false;
   1131     }
   1132     switch (msg.type)
   1133     {
   1134     case rfbFramebufferUpdate:
   1135       read_from_rfb_server(sock, ((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1);
   1136       msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
   1137       for (uint16_t i = 0; i < msg.fu.nRects; i++)
   1138       {
   1139         read_from_rfb_server(sock, (char *)&rectheader,
   1140                              sz_rfbFramebufferUpdateRectHeader);
   1141         uint16_t x = Swap16IfLE(rectheader.r.x);
   1142         uint16_t y = Swap16IfLE(rectheader.r.y);
   1143         uint16_t w = Swap16IfLE(rectheader.r.w);
   1144         uint16_t h = Swap16IfLE(rectheader.r.h);
   1145         uint32_t encoding = Swap32IfLE(rectheader.encoding);
   1146         // SoftCursorLockArea(x, y, w, h);
   1147 
   1148 #ifdef FPS_BENCHMARK
   1149         unsigned long encodingStart = micros();
   1150         reads = 0;
   1151 #endif
   1152         bool encodingResult = false;
   1153         // wdt_disable();
   1154         switch (encoding)
   1155         {
   1156         case rfbEncodingRaw:
   1157           encodingResult = _handle_raw_encoded_message(x, y, w, h);
   1158           break;
   1159         case rfbEncodingCopyRect:
   1160           encodingResult = _handle_copyrect_encoded_message(x, y, w, h);
   1161           break;
   1162 #ifdef VNC_RRE
   1163         case rfbEncodingRRE:
   1164           encodingResult = _handle_rre_encoded_message(x, y, w, h);
   1165           break;
   1166 #endif
   1167 #ifdef VNC_CORRE
   1168         case rfbEncodingCoRRE:
   1169           encodingResult = _handle_corre_encoded_message(x, y, w, h);
   1170           break;
   1171 #endif
   1172 #ifdef VNC_HEXTILE
   1173         case rfbEncodingHextile:
   1174           encodingResult = _handle_hextile_encoded_message(x, y, w, h);
   1175           break;
   1176 #endif
   1177 #ifdef VNC_ZRLE
   1178         case rfbEncodingZRLE:
   1179           encodingResult = _handle_zrle_encoded_message(x, y, w, h);
   1180           break;
   1181 #endif
   1182         case rfbEncodingPointerPos:
   1183           encodingResult = _handle_cursor_pos_message(x, y, w, h);
   1184           break;
   1185         case rfbEncodingContinuousUpdates:
   1186           encodingResult = _handle_server_continuous_updates_message(x, y, w, h);
   1187           break;
   1188         case rfbEncodingLastRect:
   1189           DEBUG_VNC("[rfbEncodingLastRect] LAST\n");
   1190           encodingResult = true;
   1191           break;
   1192 #ifdef SET_DESKTOP_SIZE
   1193         case rfbEncodingNewFBSize:
   1194           DEBUG_VNC("[rfbEncodingNewFBSize]\n");
   1195           encodingResult = true;
   1196           break;
   1197 #endif
   1198         default:
   1199           DEBUG_VNC("Unknown encoding 0x%08X %d\n", encoding, encoding);
   1200           break;
   1201         }
   1202 
   1203         display->flush();
   1204 
   1205 #ifdef FPS_BENCHMARK
   1206         unsigned long encodingTime = micros() - encodingStart;
   1207         double fps = ((double)(1 * 1000 * 1000) / (double)encodingTime);
   1208         double bps = (((double)reads) * 1000 * 1000) / ((double)encodingTime);
   1209         if (reads > 1024) // skip minor update
   1210         {
   1211           frames++;
   1212           double avg = ((double)frames) * 1000 / ((double)(millis() - connectionStart));
   1213 #ifdef ESP32
   1214           DEBUG_VNC("[Benchmark][0x%08X][%d] \tus: %lu \tfps: %s \tAvg: %s \tBytes: %d \tbps: %s \tHeap: %d\n", encoding, encoding, encodingTime, String(fps, 2).c_str(), String(avg, 2).c_str(), reads, String(bps, 2).c_str(), ESP.getFreeHeap());
   1215 #elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
   1216           DEBUG_VNC("[Benchmark][0x%08X][%d] \tus: %d \tfps: %s \tAvg: %s \tBytes: %d \tbps: %s\n", encoding, encoding, encodingTime, String(fps, 2).c_str(), String(avg, 2).c_str(), reads, String(bps, 2).c_str());
   1217 #else
   1218           DEBUG_VNC("[Benchmark][0x%08X][%d] \tus: %d \tfps: %d \tAvg: %d \tBytes: %d \tbps: %d\n", encoding, encoding, encodingTime, (int)fps, (int)avg, reads, (int)bps);
   1219 #endif
   1220         }
   1221 #endif
   1222         // wdt_enable(0);
   1223         if (!encodingResult)
   1224         {
   1225           DEBUG_VNC("[0x%08X][%d] encoding Faild!\n", encoding, encoding);
   1226           disconnect();
   1227           delay(2000);
   1228           return false;
   1229         }
   1230         else
   1231         {
   1232           // DEBUG_VNC("[0x%08X] encoding ok!\n", encoding);
   1233         }
   1234 
   1235         /* Now we may discard "soft cursor locks". */
   1236         // SoftCursorUnlockScreen();
   1237       }
   1238       break;
   1239     case rfbSetColourMapEntries:
   1240       DEBUG_VNC("SetColourMapEntries\n");
   1241       read_from_rfb_server(sock, ((char *)&msg.scme) + 1, sz_rfbSetColourMapEntriesMsg - 1);
   1242       break;
   1243     case rfbBell:
   1244       DEBUG_VNC("Bell message. Unimplemented.\n");
   1245       break;
   1246     case rfbServerCutText:
   1247       if (!_handle_server_cut_text_message(&msg))
   1248       {
   1249         disconnect();
   1250         delay(2000);
   1251         return false;
   1252       }
   1253       break;
   1254     default:
   1255       DEBUG_VNC("Unknown server message. Type: %d\n", msg.type);
   1256       disconnect();
   1257       delay(2000);
   1258       return false;
   1259       break;
   1260     }
   1261   }
   1262   return true;
   1263 }
   1264 
   1265 bool arduinoVNC::rfb_update_mouse()
   1266 {
   1267   rfbPointerEventMsg msg;
   1268 
   1269   if (mousestate.x < 0)
   1270     mousestate.x = 0;
   1271   if (mousestate.y < 0)
   1272     mousestate.y = 0;
   1273 
   1274   if (mousestate.x > opt.client.width)
   1275     mousestate.x = opt.client.width;
   1276   if (mousestate.y > opt.client.height)
   1277     mousestate.y = opt.client.height;
   1278 
   1279   msg.type = rfbPointerEvent;
   1280   msg.buttonMask = mousestate.buttonmask;
   1281 
   1282   /* scale to server resolution */
   1283   msg.x = mousestate.x; // rint(mousestate.x * opt.h_ratio);
   1284   msg.y = mousestate.y; // rint(mousestate.y * opt.v_ratio);
   1285 
   1286   msg.x = Swap16IfLE(msg.x);
   1287   msg.y = Swap16IfLE(msg.y);
   1288 
   1289   return (write_exact(sock, (char *)&msg, sz_rfbPointerEventMsg));
   1290 }
   1291 
   1292 bool arduinoVNC::rfb_send_key_event(int key, int down_flag)
   1293 {
   1294   rfbKeyEventMsg ke;
   1295 
   1296   ke.type = rfbKeyEvent;
   1297   ke.down = down_flag;
   1298   ke.key = Swap32IfLE(key);
   1299 
   1300   return (write_exact(sock, (char *)&ke, sz_rfbKeyEventMsg));
   1301 }
   1302 
   1303 //#############################################################################################
   1304 //                                      Encode handling
   1305 //#############################################################################################
   1306 
   1307 bool arduinoVNC::_handle_server_cut_text_message(rfbServerToClientMsg *msg)
   1308 {
   1309   DEBUG_VNC_HANDLE("[_handle_server_cut_text_message] work...\n");
   1310 
   1311   CARD32 size;
   1312 
   1313   if (!read_from_rfb_server(sock, ((char *)&msg->sct) + 1, sz_rfbServerCutTextMsg - 1))
   1314   {
   1315     return false;
   1316   }
   1317   size = Swap32IfLE(msg->sct.length);
   1318 
   1319   DEBUG_VNC("[_handle_server_cut_text_message] size: %d\n", size);
   1320 
   1321   if (!read_from_rfb_server(sock, raw_buffer, size))
   1322   {
   1323     return false;
   1324   }
   1325 
   1326   raw_buffer[size] = 0;
   1327 
   1328   DEBUG_VNC("[_handle_server_cut_text_message] msg: %s\n", raw_buffer);
   1329 
   1330   return true;
   1331 }
   1332 
   1333 bool arduinoVNC::_handle_raw_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1334 {
   1335   DEBUG_VNC_HANDLE("[_handle_raw_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1336 
   1337   uint16_t max_h = maxSize / 2 / w;
   1338   if (max_h == 0)
   1339   {
   1340     DEBUG_VNC("[_handle_raw_encoded_message] w too large: %d! Please increase VNC_RAW_BUFFER in VNC_config.h\n", w);
   1341   }
   1342   uint16_t sub_h = min(max_h, h);
   1343   while (h)
   1344   {
   1345     if (h < sub_h)
   1346     {
   1347       sub_h = h;
   1348     }
   1349     if (!_handle_raw_encoded_message_core(x, y, w, sub_h))
   1350     {
   1351       return false;
   1352     }
   1353     h -= sub_h;
   1354     y += sub_h;
   1355   }
   1356   return true;
   1357 }
   1358 
   1359 bool arduinoVNC::_handle_raw_encoded_message_core(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1360 {
   1361   uint32_t msgPixelTotal = (w * h);
   1362   uint32_t msgPixel = msgPixelTotal;
   1363   uint32_t msgSize = (msgPixel * 2);
   1364 
   1365   DEBUG_VNC_RAW("[_handle_raw_encoded_message_core] x: %d y: %d w: %d h: %d msgSize: %d!\n", x, y, w, h, msgSize);
   1366 
   1367   char *p = raw_buffer;
   1368   while (msgPixelTotal)
   1369   {
   1370     DEBUG_VNC_RAW("[_handle_raw_encoded_message_core] Pixel left: %d\n", msgPixelTotal);
   1371 
   1372     if (msgPixelTotal < msgPixel)
   1373     {
   1374       msgPixel = msgPixelTotal;
   1375       msgSize = (msgPixel * (opt.client.bpp / 8));
   1376     }
   1377 
   1378     if (!read_from_rfb_server(sock, p, msgSize))
   1379     {
   1380       return false;
   1381     }
   1382 
   1383     msgPixelTotal -= msgPixel;
   1384     p += msgPixel;
   1385     delay(0);
   1386   }
   1387 
   1388   display->draw_area(x, y, w, h, (uint8_t *)raw_buffer);
   1389 
   1390   DEBUG_VNC_RAW("[_handle_raw_encoded_message_core] ------------------------ Fin ------------------------\n");
   1391   return true;
   1392 }
   1393 
   1394 bool arduinoVNC::_handle_copyrect_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1395 {
   1396   DEBUG_VNC_HANDLE("[_handle_copyrect_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1397 
   1398   int src_x, src_y;
   1399 
   1400   if (!read_from_rfb_server(sock, (char *)&src_x, 2))
   1401   {
   1402     return false;
   1403   }
   1404 
   1405   if (!read_from_rfb_server(sock, (char *)&src_y, 2))
   1406   {
   1407     return false;
   1408   }
   1409 
   1410   /* If RichCursor encoding is used, we should extend our
   1411    "cursor lock area" (previously set to destination
   1412    rectangle) to the source rectangle as well. */
   1413   // SoftCursorLockArea(src_x, src_y, w, h);
   1414   display->copy_rect(Swap16IfLE(src_x), Swap16IfLE(src_y), x, y, w, h);
   1415   return true;
   1416 }
   1417 
   1418 #ifdef VNC_RRE
   1419 bool arduinoVNC::_handle_rre_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1420 {
   1421   DEBUG_VNC_HANDLE("[_handle_rre_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1422 
   1423   rfbRREHeader header;
   1424   uint16_t colour;
   1425   CARD16 rect[4];
   1426 
   1427   if (!read_from_rfb_server(sock, (char *)&header, sz_rfbRREHeader))
   1428   {
   1429     return false;
   1430   }
   1431   header.nSubrects = Swap32IfLE(header.nSubrects);
   1432 
   1433   /* draw background rect */
   1434   if (!read_from_rfb_server(sock, (char *)&colour, sizeof(colour)))
   1435   {
   1436     return false;
   1437   }
   1438 
   1439   display->draw_rect(x, y, w, h, colour);
   1440 
   1441   /* subrect pixel values */
   1442   for (uint32_t i = 0; i < header.nSubrects; i++)
   1443   {
   1444     if (!read_from_rfb_server(sock, (char *)&colour, sizeof(colour)))
   1445     {
   1446       return false;
   1447     }
   1448     if (!read_from_rfb_server(sock, (char *)&rect, sizeof(rect)))
   1449       return false;
   1450     display->draw_rect(
   1451         Swap16IfLE(rect[0]) + x, Swap16IfLE(rect[1]) + y,
   1452         Swap16IfLE(rect[2]), Swap16IfLE(rect[3]), colour);
   1453   }
   1454 
   1455   return true;
   1456 }
   1457 #endif // #ifdef VNC_RRE
   1458 
   1459 #ifdef VNC_CORRE
   1460 bool arduinoVNC::_handle_corre_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1461 {
   1462   DEBUG_VNC_HANDLE("[_handle_corre_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1463 
   1464   rfbRREHeader header;
   1465   uint16_t colour;
   1466   CARD8 rect[4];
   1467 
   1468   if (!read_from_rfb_server(sock, (char *)&colour, sizeof(colour)))
   1469   {
   1470     return false;
   1471   }
   1472   if (!read_from_rfb_server(sock, (char *)&header, sz_rfbRREHeader))
   1473   {
   1474     return false;
   1475   }
   1476   header.nSubrects = Swap32IfLE(header.nSubrects);
   1477 
   1478   /* draw background rect */
   1479   if (!read_from_rfb_server(sock, (char *)&colour, sizeof(colour)))
   1480   {
   1481     return false;
   1482   }
   1483   display->draw_rect(x, y, w, h, colour);
   1484 
   1485   /* subrect pixel values */
   1486   for (uint32_t i = 0; i < header.nSubrects; i++)
   1487   {
   1488     if (!read_from_rfb_server(sock, (char *)&colour, sizeof(colour)))
   1489     {
   1490       return false;
   1491     }
   1492     if (!read_from_rfb_server(sock, (char *)&rect, sizeof(rect)))
   1493     {
   1494       return false;
   1495     }
   1496     display->draw_rect(
   1497         Swap16IfLE(rect[0]) + x, Swap16IfLE(rect[1]) + y,
   1498         Swap16IfLE(rect[2]), Swap16IfLE(rect[3]), colour);
   1499   }
   1500   return true;
   1501 }
   1502 #endif // #ifdef VNC_CORRE
   1503 
   1504 #ifdef VNC_HEXTILE
   1505 bool arduinoVNC::_handle_hextile_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1506 {
   1507   DEBUG_VNC_HANDLE("[_handle_hextile_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1508 
   1509   uint16_t rect_x, rect_y, rect_w, rect_h, i = 0, j = 0;
   1510   uint16_t rect_xW, rect_yW;
   1511 
   1512   uint16_t tile_w = 16, tile_h = 16;
   1513   uint16_t remaining_w, remaining_h;
   1514 
   1515   CARD8 subrect_encoding;
   1516 
   1517   uint16_t fgColor;
   1518   uint16_t bgColor;
   1519 
   1520   DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1521 
   1522   rect_w = remaining_w = w;
   1523   rect_h = remaining_h = h;
   1524   rect_x = x;
   1525   rect_y = y;
   1526 
   1527   /* the rect is divided into tiles of width and height 16. Iterate over
   1528    * those */
   1529   while (i < rect_h)
   1530   {
   1531     /* the last tile in a column could be smaller than 16 */
   1532     if (remaining_h < 16)
   1533     {
   1534       tile_h = remaining_h;
   1535     }
   1536     else
   1537     {
   1538       remaining_h -= 16;
   1539     }
   1540 
   1541     j = 0;
   1542     while (j < rect_w)
   1543     {
   1544       /* the last tile in a row could also be smaller */
   1545       if (remaining_w < 16)
   1546       {
   1547         tile_w = remaining_w;
   1548       }
   1549       else
   1550       {
   1551         remaining_w -= 16;
   1552       }
   1553 
   1554       rect_xW = rect_x + j;
   1555       rect_yW = rect_y + i;
   1556 
   1557       if (!read_from_rfb_server(sock, (char *)&subrect_encoding, 1))
   1558       {
   1559         return false;
   1560       }
   1561 
   1562       DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] subrect_encoding: %d, subrect: x: %d y: %d w: %d h: %d\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1563 
   1564       /* first, check if the raw bit is set */
   1565       if (subrect_encoding & rfbHextileRaw)
   1566       {
   1567         DEBUG_VNC_HEXTILE("[hextile call raw] x: %d y: %d w: %d h: %d!\n", rect_xW, rect_yW, tile_w, tile_h);
   1568         if (!_handle_raw_encoded_message_core(rect_xW, rect_yW, tile_w, tile_h))
   1569         {
   1570           return false;
   1571         }
   1572       }
   1573       else
   1574       { /* subrect encoding is not raw */
   1575 
   1576         /* check whether theres a new bg or fg colour specified */
   1577         if (subrect_encoding & rfbHextileBackgroundSpecified)
   1578         {
   1579           if (!read_from_rfb_server(sock, (char *)&bgColor, sizeof(bgColor)))
   1580           {
   1581             return false;
   1582           }
   1583         }
   1584 
   1585         if (subrect_encoding & rfbHextileForegroundSpecified)
   1586         {
   1587           if (!read_from_rfb_server(sock, (char *)&fgColor, sizeof(fgColor)))
   1588           {
   1589             return false;
   1590           }
   1591         }
   1592 
   1593         DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] subrect: x: %d y: %d w: %d h: %d\n", rect_xW, rect_yW, tile_w, tile_h);
   1594 
   1595         uint16_t tile_size = tile_w * tile_h;
   1596         if (tile_size > FB_SIZE)
   1597         {
   1598           DEBUG_VNC("[_handle_hextile_encoded_message] ttile too large: %d x % d! Please increase FB_SIZE in VNC_config.h\n", tile_w, tile_h);
   1599           return false;
   1600         }
   1601 
   1602         /* fill the background */
   1603         uint16_t *p = framebuffer;
   1604         uint16_t i = tile_size;
   1605         uint16_t j, w, delta_x;
   1606         while (i--)
   1607         {
   1608           *p++ = bgColor;
   1609         }
   1610 
   1611         if (subrect_encoding & rfbHextileAnySubrects)
   1612         {
   1613           uint8_t nr_subr = 0;
   1614           if (!read_from_rfb_server(sock, (char *)&nr_subr, 1))
   1615           {
   1616             return false;
   1617           }
   1618           DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] nr_subr: %d\n", nr_subr);
   1619           if (nr_subr)
   1620           {
   1621             if (subrect_encoding & rfbHextileSubrectsColoured)
   1622             {
   1623               if (!read_from_rfb_server(sock, raw_buffer, nr_subr * 4))
   1624               {
   1625                 return false;
   1626               }
   1627 
   1628               HextileSubrectsColoured_t *bufPC = (HextileSubrectsColoured_t *)raw_buffer;
   1629               for (uint8_t n = 0; n < nr_subr; n++)
   1630               {
   1631                 DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] Coloured nr_subr: %d bufPC: %d, %d, %d, %d\n", n, bufPC->x, bufPC->y, bufPC->w, bufPC->h);
   1632                 p = framebuffer + (bufPC->y * tile_w) + bufPC->x;
   1633                 w = bufPC->w + 1;
   1634                 i = w;
   1635                 j = bufPC->h + 1;
   1636                 delta_x = tile_w - w;
   1637                 while (j--)
   1638                 {
   1639                   while (i--)
   1640                   {
   1641                     *p++ = bufPC->color;
   1642                   }
   1643                   i = w;
   1644                   p += delta_x;
   1645                 }
   1646                 bufPC++;
   1647               }
   1648             }
   1649             else
   1650             {
   1651               if (!read_from_rfb_server(sock, raw_buffer, nr_subr * 2))
   1652               {
   1653                 return false;
   1654               }
   1655 
   1656               HextileSubrects_t *bufP = (HextileSubrects_t *)raw_buffer;
   1657               for (uint8_t n = 0; n < nr_subr; n++)
   1658               {
   1659                 DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] nr_subr: %d bufP: %d, %d, %d, %d\n", n, bufP->x, bufP->y, bufP->w, bufP->h);
   1660                 p = framebuffer + (bufP->y * tile_w) + bufP->x;
   1661                 w = bufP->w + 1;
   1662                 i = w;
   1663                 j = bufP->h + 1;
   1664                 delta_x = tile_w - w;
   1665                 while (j--)
   1666                 {
   1667                   while (i--)
   1668                   {
   1669                     *p++ = fgColor;
   1670                   }
   1671                   i = w;
   1672                   p += delta_x;
   1673                 }
   1674                 bufP++;
   1675               }
   1676             }
   1677           }
   1678         }
   1679         display->draw_area(rect_xW, rect_yW, tile_w, tile_h, (uint8_t *)framebuffer);
   1680       }
   1681       j += 16;
   1682       delay(0);
   1683     }
   1684     remaining_w = w;
   1685     tile_w = 16; /* reset for next row */
   1686     i += 16;
   1687   }
   1688 
   1689   DEBUG_VNC_HEXTILE("[_handle_hextile_encoded_message] ------------------------ Fin ------------------------\n");
   1690   return true;
   1691 }
   1692 #endif // #ifdef VNC_HEXTILE
   1693 
   1694 #ifdef VNC_ZRLE
   1695 bool arduinoVNC::_handle_zrle_encoded_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1696 {
   1697   DEBUG_VNC_HANDLE("[_handle_zrle_encoded_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1698 
   1699   rfbZlibHeader zlh;
   1700   if (!read_from_rfb_server(sock, (char *)&zlh, sz_rfbZlibHeader))
   1701   {
   1702     return false;
   1703   }
   1704   uint32_t len = Swap32IfLE(zlh.nBytes);
   1705 
   1706   DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] x: %d y: %d w: %d h: %d len: %d!\n", x, y, w, h, len);
   1707 
   1708   if (!zin_buffer)
   1709   {
   1710     zin_buffer = (uint8_t *)malloc(len);
   1711     allocated_zin = len;
   1712   }
   1713   else
   1714   {
   1715     if (allocated_zin < len)
   1716     {
   1717       zin_buffer = (uint8_t *)realloc(zin_buffer, len);
   1718     }
   1719   }
   1720   if (!zin_buffer)
   1721   {
   1722     DEBUG_VNC("zin_buffer malloc failed!\n");
   1723   }
   1724   if (!read_from_rfb_server(sock, (char *)zin_buffer, len))
   1725   {
   1726     DEBUG_VNC("Failed reading from input file!\n");
   1727     return false;
   1728   }
   1729   zin_buf_size = len;
   1730   zin_buf_ofs = 0;
   1731   zout_buf_idx = 0;
   1732   zout_buf_remain = 0;
   1733 
   1734   uint16_t rect_x, rect_y, rect_w, rect_h, i = 0, j = 0;
   1735   uint16_t rect_xW, rect_yW;
   1736 
   1737   uint16_t tile_w = 64, tile_h = 64;
   1738   uint16_t remaining_w, remaining_h;
   1739   size_t tile_size;
   1740   uint16_t *p;
   1741 
   1742   CARD8 subrect_encoding;
   1743 
   1744   uint16_t color;
   1745   size_t idx;
   1746   size_t paletteSize = 0;
   1747 
   1748   rect_w = remaining_w = w;
   1749   rect_h = remaining_h = h;
   1750   rect_x = x;
   1751   rect_y = y;
   1752 
   1753   size_t runLengthCount = 0;
   1754   uint8_t runLenMinus1;
   1755   uint16_t runLength;
   1756 
   1757   while (i < rect_h)
   1758   {
   1759     /* the rect is divided into tiles of width and height 64. Iterate over
   1760      * those */
   1761     /* the last tile in a column could be smaller than 16 */
   1762     if (remaining_h < 64)
   1763     {
   1764       tile_h = remaining_h;
   1765     }
   1766 
   1767     /* the last tile in a row could also be smaller */
   1768     if (remaining_w < 64)
   1769     {
   1770       tile_w = remaining_w;
   1771     }
   1772     else
   1773     {
   1774       remaining_w -= 64;
   1775     }
   1776 
   1777     tile_size = tile_w * tile_h;
   1778     rect_xW = rect_x + j;
   1779     rect_yW = rect_y + i;
   1780 
   1781     read_from_z(&subrect_encoding, 1);
   1782 
   1783     if (subrect_encoding == rfbTrleRaw)
   1784     {
   1785       // DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d RAW x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1786       read_from_z((uint8_t *)framebuffer, tile_size * 2);
   1787       display->draw_area(rect_xW, rect_yW, tile_w, tile_h, (uint8_t *)framebuffer);
   1788     }
   1789     else
   1790     {
   1791       paletteSize = subrect_encoding & 127;
   1792 
   1793       // DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] subrect_encoding: %d, paletteSize: %d, subrect: x: %d y: %d w: %d h: %d\n", subrect_encoding, paletteSize, rect_xW, rect_yW, tile_w, tile_h);
   1794 
   1795       read_from_z((uint8_t *)&palette, paletteSize * 2);
   1796 
   1797       if (subrect_encoding == rfbTrleSolid)
   1798       {
   1799         DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d SOLID x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1800         display->draw_rect(rect_xW, rect_yW, tile_w, tile_h, palette[0]);
   1801       }
   1802       else if (subrect_encoding <= rfbTrleReusePackedPalette)
   1803       {
   1804         p = framebuffer;
   1805         uint8_t data = 0;
   1806         if (paletteSize == 2) // 1-bit
   1807         {
   1808           DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d 1-bit, x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1809 
   1810           for (int hidx = 0; hidx < tile_h; ++hidx)
   1811           {
   1812             for (idx = 0; idx < tile_w; ++idx)
   1813             {
   1814               if ((idx & 0b111) == 0) // new byte
   1815               {
   1816                 read_from_z(&data, 1);
   1817               }
   1818               else
   1819               {
   1820                 data <<= 1;
   1821               }
   1822               *p++ = palette[(data >> 7) & 127];
   1823             }
   1824           }
   1825         }
   1826         else if (paletteSize <= 4) // 3-4 palettes, 2-bit
   1827         {
   1828           DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d 2-bit, x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1829 
   1830           for (int hidx = 0; hidx < tile_h; ++hidx)
   1831           {
   1832             for (idx = 0; idx < tile_w; ++idx)
   1833             {
   1834               if ((idx & 0b11) == 0) // new byte
   1835               {
   1836                 read_from_z(&data, 1);
   1837               }
   1838               else
   1839               {
   1840                 data <<= 2;
   1841               }
   1842               *p++ = palette[(data >> 6) & 127];
   1843             }
   1844           }
   1845         }
   1846         else if (paletteSize <= 16) // 5-16 palettes, 4-bit
   1847         {
   1848           DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d 4-bit, x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1849 
   1850           for (int hidx = 0; hidx < tile_h; ++hidx)
   1851           {
   1852             for (idx = 0; idx < tile_w; ++idx)
   1853             {
   1854               if ((idx & 1) == 0) // new byte
   1855               {
   1856                 read_from_z(&data, 1);
   1857               }
   1858               else
   1859               {
   1860                 data <<= 4;
   1861               }
   1862               *p++ = palette[(data >> 4) & 127];
   1863             }
   1864           }
   1865         }
   1866         else // > 16 palettes, 8-bit
   1867         {
   1868           DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d 8-bit, x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1869 
   1870           for (idx = 0; idx < tile_size; ++idx)
   1871           {
   1872             read_from_z(&data, 1);
   1873             *p++ = palette[data & 127];
   1874           }
   1875         }
   1876 
   1877         display->draw_area(rect_xW, rect_yW, tile_w, tile_h, (uint8_t *)framebuffer);
   1878       }
   1879       else if (subrect_encoding == rfbTrlePlainRLE)
   1880       {
   1881         DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d Plain RLE x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1882         p = framebuffer;
   1883         runLengthCount = 0;
   1884         while (runLengthCount < tile_size)
   1885         {
   1886           read_from_z((uint8_t *)&color, 2);
   1887 
   1888           runLength = 1;
   1889           do
   1890           {
   1891             read_from_z(&runLenMinus1, 1);
   1892 
   1893             runLength += runLenMinus1;
   1894           } while (runLenMinus1 == 255);
   1895 
   1896           runLengthCount += runLength;
   1897           if (runLengthCount > tile_size)
   1898           {
   1899             DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d Plain RLE runLengthCount(%d) > tile_size(%d)!\n", subrect_encoding, runLengthCount, tile_size);
   1900           }
   1901           else
   1902           {
   1903             while (runLength--)
   1904             {
   1905               *p++ = color;
   1906             }
   1907           }
   1908         }
   1909 
   1910         display->draw_area(rect_xW, rect_yW, tile_w, tile_h, (uint8_t *)framebuffer);
   1911       }
   1912       else // Palette RLE
   1913       {
   1914         DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d Palette RLE x: %d y: %d w: %d h: %d!\n", subrect_encoding, rect_xW, rect_yW, tile_w, tile_h);
   1915         p = framebuffer;
   1916         runLengthCount = 0;
   1917         while (runLengthCount < tile_size)
   1918         {
   1919           read_from_z((uint8_t *)&idx, 1);
   1920 
   1921           runLength = 1;
   1922           if ((idx & 128) != 0)
   1923           {
   1924             do
   1925             {
   1926               read_from_z(&runLenMinus1, 1);
   1927 
   1928               runLength += runLenMinus1;
   1929             } while (runLenMinus1 == 255);
   1930           }
   1931 
   1932           color = palette[idx & 127];
   1933 
   1934           runLengthCount += runLength;
   1935           // DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] Palette RLE idx: %d, runLength: %d, runLengthCount: %d.\n", idx, runLength, runLengthCount);
   1936           if (runLengthCount > tile_size)
   1937           {
   1938             DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] %d Palette RLE runLengthCount(%d) > tile_size(%d)!\n", subrect_encoding, runLengthCount, tile_size);
   1939           }
   1940           else
   1941           {
   1942             while (runLength--)
   1943             {
   1944               *p++ = color;
   1945             }
   1946           }
   1947         }
   1948 
   1949         display->draw_area(rect_xW, rect_yW, tile_w, tile_h, (uint8_t *)framebuffer);
   1950       }
   1951     }
   1952 
   1953     // next tile
   1954     j += 64;
   1955     if (j >= rect_w)
   1956     {
   1957       j = 0;
   1958       remaining_w = w;
   1959       tile_w = 64; /* reset for next row */
   1960       i += 64;
   1961 
   1962       if (remaining_h >= 64)
   1963       {
   1964         remaining_h -= 64;
   1965       }
   1966       else
   1967       {
   1968         break;
   1969       }
   1970     }
   1971 
   1972     delay(0);
   1973     // DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] loop i: %d, j: %d\n", i, j);
   1974   }
   1975 
   1976   DEBUG_VNC_ZRLE("[_handle_zrle_encoded_message] ------------------------ Fin ------------------------\n");
   1977   return true;
   1978 }
   1979 #endif // #ifdef VNC_ZRLE
   1980 
   1981 bool arduinoVNC::_handle_cursor_pos_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1982 {
   1983   DEBUG_VNC_HANDLE("[_handle_cursor_pos_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1984   return true;
   1985 }
   1986 
   1987 bool arduinoVNC::_handle_server_continuous_updates_message(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
   1988 {
   1989   DEBUG_VNC_HANDLE("[_handle_server_continuous_updates_message] x: %d y: %d w: %d h: %d!\n", x, y, w, h);
   1990   return true;
   1991 }
   1992 
   1993 //#############################################################################################
   1994 //                                      Encryption
   1995 //#############################################################################################
   1996 
   1997 void arduinoVNC::vncRandomBytes(unsigned char *bytes)
   1998 {
   1999 #ifdef ESP8266
   2000   srand(RANDOM_REG32);
   2001 #else
   2002   // todo find better seed
   2003   srand(millis());
   2004 #endif
   2005   for (int i = 0; i < CHALLENGESIZE; i++)
   2006   {
   2007     bytes[i] = (unsigned char)(rand() & 255);
   2008   }
   2009 }
   2010 
   2011 void arduinoVNC::vncEncryptBytes(unsigned char *bytes, char *passwd)
   2012 {
   2013   unsigned char key[8];
   2014   size_t i;
   2015 
   2016   /* key is simply password padded with nulls */
   2017 
   2018   for (i = 0; i < 8; i++)
   2019   {
   2020     if (i < strlen(passwd))
   2021     {
   2022       key[i] = passwd[i];
   2023     }
   2024     else
   2025     {
   2026       key[i] = 0;
   2027     }
   2028   }
   2029 
   2030   deskey(key, EN0);
   2031 
   2032   for (i = 0; i < CHALLENGESIZE; i += 8)
   2033   {
   2034     des(bytes + i, bytes + i);
   2035   }
   2036 }