Make this VNC server interoperate with OS X's builtin VNC client

by pretending to support V3.3 of the protocol and implementing dummy VNC
authentication.

Also initializes the pixel-format defaults in case a client does not
send the "SetPixelFormat" message.

Bug: 151186027
Change-Id: I9c919a542dd917fc139cce61640d87b08145c071
diff --git a/host/frontend/vnc_server/vnc_client_connection.cpp b/host/frontend/vnc_server/vnc_client_connection.cpp
index b4cc24b..c15d46c 100644
--- a/host/frontend/vnc_server/vnc_client_connection.cpp
+++ b/host/frontend/vnc_server/vnc_client_connection.cpp
@@ -195,12 +195,22 @@
 
 void VncClientConnection::SetupProtocol() {
   static constexpr char kRFBVersion[] = "RFB 003.008\n";
+  static constexpr char kRFBVersionOld[] = "RFB 003.003\n";
   static constexpr auto kVersionLen = (sizeof kRFBVersion) - 1;
   client_.SendNoSignal(reinterpret_cast<const std::uint8_t*>(kRFBVersion),
                        kVersionLen);
   auto client_protocol = client_.Recv(kVersionLen);
   if (std::memcmp(&client_protocol[0], kRFBVersion,
                   std::min(kVersionLen, client_protocol.size())) != 0) {
+    if (!std::memcmp(
+                &client_protocol[0],
+                kRFBVersionOld,
+                std::min(kVersionLen, client_protocol.size()))) {
+        // We'll deal with V3.3 as well.
+        client_is_old_ = true;
+        return;
+    }
+
     client_protocol.push_back('\0');
     LOG(ERROR) << "vnc client wants a different protocol: "
                << reinterpret_cast<const char*>(&client_protocol[0]);
@@ -208,6 +218,23 @@
 }
 
 void VncClientConnection::SetupSecurityType() {
+  if (client_is_old_) {
+    static constexpr std::uint8_t kVNCSecurity[4] = { 0x00, 0x00, 0x00, 0x02 };
+    client_.SendNoSignal(kVNCSecurity);
+
+    static constexpr std::uint8_t kChallenge[16] =
+        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+    client_.SendNoSignal(kChallenge);
+
+    auto clientResponse = client_.Recv(16);
+    (void)clientResponse;  // Accept any response, we're not interested in actual security.
+
+    static constexpr std::uint8_t kSuccess[4] = { 0x00, 0x00, 0x00, 0x00 };
+    client_.SendNoSignal(kSuccess);
+    return;
+  }
+
   static constexpr std::uint8_t kNoneSecurity = 0x1;
   // The first '0x1' indicates the number of items that follow
   static constexpr std::uint8_t kOnlyNoneSecurity[] = {0x01, kNoneSecurity};
diff --git a/host/frontend/vnc_server/vnc_client_connection.h b/host/frontend/vnc_server/vnc_client_connection.h
index 73beae1..9f4fb96 100644
--- a/host/frontend/vnc_server/vnc_client_connection.h
+++ b/host/frontend/vnc_server/vnc_client_connection.h
@@ -151,20 +151,22 @@
 
   PixelFormat pixel_format_ GUARDED_BY(m_) = {
       std::uint8_t{32},  // bits per pixel
-      std::uint8_t{8},   // depth
-      std::uint8_t{},    // big_endian
-      std::uint8_t{},    // true_color
-      std::uint16_t{},   // red_max, (maxes not used when true color flag is 0)
-      std::uint16_t{},   // green_max
-      std::uint16_t{},   // blue_max
-      std::uint8_t{},  // red_shift (shifts not used when true color flag is 0)
-      std::uint8_t{},  // green_shift
-      std::uint8_t{},  // blue_shift
+      std::uint8_t{24},   // depth
+      std::uint8_t{0},    // big_endian
+      std::uint8_t{1},    // true_color
+      std::uint16_t{0xff},   // red_max, (maxes not used when true color flag is 0)
+      std::uint16_t{0xff},   // green_max
+      std::uint16_t{0xff},   // blue_max
+      std::uint8_t{0},  // red_shift (shifts not used when true color flag is 0)
+      std::uint8_t{8},  // green_shift
+      std::uint8_t{16},  // blue_shift
   };
 
   bool supports_desktop_size_encoding_ = false;
   ScreenOrientation current_orientation_ GUARDED_BY(m_) =
       ScreenOrientation::Portrait;
+
+  bool client_is_old_ = false;
 };
 
 }  // namespace vnc