/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "host/frontend/vnc_server/vnc_client_connection.h"

#include <netinet/in.h>
#include <sys/time.h>

#include <algorithm>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>
#include "host/frontend/vnc_server/keysyms.h"
#include "host/frontend/vnc_server/mocks.h"
#include "host/frontend/vnc_server/tcp_socket.h"
#include "host/frontend/vnc_server/vnc_utils.h"

using cvd::vnc::Message;
using cvd::vnc::Stripe;
using cvd::vnc::StripePtrVec;
using cvd::vnc::VncClientConnection;

DEFINE_bool(debug_client, false, "Turn on detailed logging for the client");

#define DLOG(LEVEL) \
  if (FLAGS_debug_client) LOG(LEVEL)

namespace {
class BigEndianChecker {
 public:
  BigEndianChecker() {
    uint32_t u = 1;
    is_big_endian_ = *reinterpret_cast<const char*>(&u) == 0;
  }
  bool operator()() const { return is_big_endian_; }

 private:
  bool is_big_endian_{};
};

const BigEndianChecker ImBigEndian;

constexpr int32_t kDesktopSizeEncoding = -223;
constexpr int32_t kTightEncoding = 7;

// These are the lengths not counting the first byte. The first byte
// indicates the message type.
constexpr size_t kSetPixelFormatLength = 19;
constexpr size_t kFramebufferUpdateRequestLength = 9;
constexpr size_t kSetEncodingsLength = 3;  // more bytes follow
constexpr size_t kKeyEventLength = 7;
constexpr size_t kPointerEventLength = 5;
constexpr size_t kClientCutTextLength = 7;  // more bytes follow

void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b) {
  msg->push_back(b);
}

void AppendInNetworkByteOrder(Message* msg, const std::uint16_t s) {
  const std::uint16_t n = htons(s);
  auto p = reinterpret_cast<const std::uint8_t*>(&n);
  msg->insert(msg->end(), p, p + sizeof n);
}

void AppendInNetworkByteOrder(Message* msg, const std::uint32_t w) {
  const std::uint32_t n = htonl(w);
  auto p = reinterpret_cast<const std::uint8_t*>(&n);
  msg->insert(msg->end(), p, p + sizeof n);
}

void AppendInNetworkByteOrder(Message* msg, const int32_t w) {
  std::uint32_t u{};
  std::memcpy(&u, &w, sizeof u);
  AppendInNetworkByteOrder(msg, u);
}

void AppendInNetworkByteOrder(Message* msg, const std::string& str) {
  msg->insert(msg->end(), str.begin(), str.end());
}

void AppendToMessage(Message*) {}

template <typename T, typename... Ts>
void AppendToMessage(Message* msg, T v, Ts... vals) {
  AppendInNetworkByteOrder(msg, v);
  AppendToMessage(msg, vals...);
}

template <typename... Ts>
Message CreateMessage(Ts... vals) {
  Message m;
  AppendToMessage(&m, vals...);
  return m;
}

std::string HostName() {
  // Localhost is good enough for local development and to connect through ssh
  // tunneling, for something else this probably needs to change.
  return "localhost";
}

std::uint16_t uint16_tAt(const void* p) {
  std::uint16_t u{};
  std::memcpy(&u, p, sizeof u);
  return ntohs(u);
}

std::uint32_t uint32_tAt(const void* p) {
  std::uint32_t u{};
  std::memcpy(&u, p, sizeof u);
  return ntohl(u);
}

std::int32_t int32_tAt(const void* p) {
  std::uint32_t u{};
  std::memcpy(&u, p, sizeof u);
  u = ntohl(u);
  std::int32_t s{};
  std::memcpy(&s, &u, sizeof s);
  return s;
}

std::uint32_t RedVal(std::uint32_t pixel) {
  return (pixel >> GceFrameBuffer::kRedShift) &
         ((0x1 << GceFrameBuffer::kRedBits) - 1);
}

std::uint32_t BlueVal(std::uint32_t pixel) {
  return (pixel >> GceFrameBuffer::kBlueShift) &
         ((0x1 << GceFrameBuffer::kBlueBits) - 1);
}

std::uint32_t GreenVal(std::uint32_t pixel) {
  return (pixel >> GceFrameBuffer::kGreenShift) &
         ((0x1 << GceFrameBuffer::kGreenBits) - 1);
}
}  // namespace
namespace cvd {
namespace vnc {
bool operator==(const VncClientConnection::FrameBufferUpdateRequest& lhs,
                const VncClientConnection::FrameBufferUpdateRequest& rhs) {
  return lhs.x_pos == rhs.x_pos && lhs.y_pos == rhs.y_pos &&
         lhs.width == rhs.width && lhs.height == rhs.height;
}

bool operator!=(const VncClientConnection::FrameBufferUpdateRequest& lhs,
                const VncClientConnection::FrameBufferUpdateRequest& rhs) {
  return !(lhs == rhs);
}
}  // namespace vnc
}  // namespace cvd

VncClientConnection::VncClientConnection(ClientSocket client,
                                         VirtualInputs* virtual_inputs,
                                         BlackBoard* bb, bool aggressive)
    : client_{std::move(client)},
      sensor_event_hal_{cvd::SharedFD::SocketSeqPacketClient(
          gce_sensors_message::kSensorsHALSocketName)},
      virtual_inputs_{virtual_inputs},
      bb_{bb} {
  frame_buffer_request_handler_tid_ = std::thread(
      &VncClientConnection::FrameBufferUpdateRequestHandler, this, aggressive);
}

VncClientConnection::~VncClientConnection() {
  {
    std::lock_guard<std::mutex> guard(m_);
    closed_ = true;
  }
  bb_->StopWaiting(this);
  frame_buffer_request_handler_tid_.join();
}

void VncClientConnection::StartSession() {
  LOG(INFO) << "Starting session";
  SetupProtocol();
  LOG(INFO) << "Protocol set up";
  if (client_.closed()) {
    return;
  }
  SetupSecurityType();
  LOG(INFO) << "Security type set";
  if (client_.closed()) {
    return;
  }
  GetClientInit();
  LOG(INFO) << "Gotten client init";
  if (client_.closed()) {
    return;
  }
  SendServerInit();
  LOG(INFO) << "Sent server init";
  if (client_.closed()) {
    return;
  }
  NormalSession();
  LOG(INFO) << "vnc session terminated";
}

bool VncClientConnection::closed() {
  std::lock_guard<std::mutex> guard(m_);
  return closed_;
}

void VncClientConnection::SetupProtocol() {
  static constexpr char kRFBVersion[] = "RFB 003.008\n";
  static constexpr auto kVersionLen = (sizeof kRFBVersion) - 1;
  client_.Send(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) {
    client_protocol.push_back('\0');
    LOG(ERROR) << "vnc client wants a different protocol: "
               << reinterpret_cast<const char*>(&client_protocol[0]);
  }
}

void VncClientConnection::SetupSecurityType() {
  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};
  client_.Send(kOnlyNoneSecurity);
  auto client_security = client_.Recv(1);
  if (client_.closed()) {
    return;
  }
  if (client_security.front() != kNoneSecurity) {
    LOG(ERROR) << "vnc client is asking for security type "
               << static_cast<int>(client_security.front());
  }
  static constexpr std::uint8_t kZero[4] = {};
  client_.Send(kZero);
}

void VncClientConnection::GetClientInit() {
  auto client_shared = client_.Recv(1);
}

void VncClientConnection::SendServerInit() {
  const std::string server_name = HostName();
  std::lock_guard<std::mutex> guard(m_);
  auto server_init = CreateMessage(
      static_cast<std::uint16_t>(ScreenWidth()),
      static_cast<std::uint16_t>(ScreenHeight()), pixel_format_.bits_per_pixel,
      pixel_format_.depth, pixel_format_.big_endian, pixel_format_.true_color,
      pixel_format_.red_max, pixel_format_.green_max, pixel_format_.blue_max,
      pixel_format_.red_shift, pixel_format_.green_shift,
      pixel_format_.blue_shift, std::uint16_t{},  // padding
      std::uint8_t{},                             // padding
      static_cast<std::uint32_t>(server_name.size()), server_name);
  client_.Send(server_init);
}

Message VncClientConnection::MakeFrameBufferUpdateHeader(
    std::uint16_t num_stripes) {
  return CreateMessage(std::uint8_t{0},  // message-type
                       std::uint8_t{},   // padding
                       std::uint16_t{num_stripes});
}

void VncClientConnection::AppendRawStripeHeader(Message* frame_buffer_update,
                                                const Stripe& stripe) {
  static constexpr int32_t kRawEncoding = 0;
  AppendToMessage(frame_buffer_update, std::uint16_t{stripe.x},
                  std::uint16_t{stripe.y}, std::uint16_t{stripe.width},
                  std::uint16_t{stripe.height}, kRawEncoding);
}

void VncClientConnection::AppendJpegSize(Message* frame_buffer_update,
                                         size_t jpeg_size) {
  constexpr size_t kJpegSizeOneByteMax = 127;
  constexpr size_t kJpegSizeTwoByteMax = 16383;
  constexpr size_t kJpegSizeThreeByteMax = 4194303;

  if (jpeg_size <= kJpegSizeOneByteMax) {
    AppendToMessage(frame_buffer_update, static_cast<std::uint8_t>(jpeg_size));
  } else if (jpeg_size <= kJpegSizeTwoByteMax) {
    auto sz = static_cast<std::uint32_t>(jpeg_size);
    AppendToMessage(frame_buffer_update,
                    static_cast<std::uint8_t>((sz & 0x7F) | 0x80),
                    static_cast<std::uint8_t>((sz >> 7) & 0xFF));
  } else {
    if (jpeg_size > kJpegSizeThreeByteMax) {
      LOG(FATAL) << "jpeg size is too big: " << jpeg_size << " must be under "
                 << kJpegSizeThreeByteMax;
    }
    const auto sz = static_cast<std::uint32_t>(jpeg_size);
    AppendToMessage(frame_buffer_update,
                    static_cast<std::uint8_t>((sz & 0x7F) | 0x80),
                    static_cast<std::uint8_t>(((sz >> 7) & 0x7F) | 0x80),
                    static_cast<std::uint8_t>((sz >> 14) & 0xFF));
  }
}

void VncClientConnection::AppendRawStripe(Message* frame_buffer_update,
                                          const Stripe& stripe) const {
  using Pixel = GceFrameBuffer::Pixel;
  auto& fbu = *frame_buffer_update;
  AppendRawStripeHeader(&fbu, stripe);
  auto init_size = fbu.size();
  fbu.insert(fbu.end(), stripe.raw_data.begin(), stripe.raw_data.end());
  for (size_t i = init_size; i < fbu.size(); i += sizeof(Pixel)) {
    CHECK((i + sizeof(Pixel)) < fbu.size());
    Pixel raw_pixel{};
    std::memcpy(&raw_pixel, &fbu[i], sizeof raw_pixel);
    auto red = RedVal(raw_pixel);
    auto green = GreenVal(raw_pixel);
    auto blue = BlueVal(raw_pixel);
    Pixel pixel = Pixel{red} << pixel_format_.red_shift |
                  Pixel{blue} << pixel_format_.blue_shift |
                  Pixel{green} << pixel_format_.green_shift;

    if (bool(pixel_format_.big_endian) != ImBigEndian()) {
      // flip them bits (refactor into function)
      auto p = reinterpret_cast<char*>(&pixel);
      std::swap(p[0], p[3]);
      std::swap(p[1], p[2]);
    }
    CHECK(i + sizeof pixel <= fbu.size());
    std::memcpy(&fbu[i], &pixel, sizeof pixel);
  }
}

Message VncClientConnection::MakeRawFrameBufferUpdate(
    const StripePtrVec& stripes) const {
  auto fbu =
      MakeFrameBufferUpdateHeader(static_cast<std::uint16_t>(stripes.size()));
  for (auto& stripe : stripes) {
    AppendRawStripe(&fbu, *stripe);
  }
  return fbu;
}

void VncClientConnection::AppendJpegStripeHeader(Message* frame_buffer_update,
                                                 const Stripe& stripe) {
  static constexpr std::uint8_t kJpegEncoding = 0x90;
  AppendToMessage(frame_buffer_update, stripe.x, stripe.y, stripe.width,
                  stripe.height, kTightEncoding, kJpegEncoding);
  AppendJpegSize(frame_buffer_update, stripe.jpeg_data.size());
}

void VncClientConnection::AppendJpegStripe(Message* frame_buffer_update,
                                           const Stripe& stripe) {
  AppendJpegStripeHeader(frame_buffer_update, stripe);
  frame_buffer_update->insert(frame_buffer_update->end(),
                              stripe.jpeg_data.begin(), stripe.jpeg_data.end());
}

Message VncClientConnection::MakeJpegFrameBufferUpdate(
    const StripePtrVec& stripes) {
  auto fbu =
      MakeFrameBufferUpdateHeader(static_cast<std::uint16_t>(stripes.size()));
  for (auto& stripe : stripes) {
    AppendJpegStripe(&fbu, *stripe);
  }
  return fbu;
}

Message VncClientConnection::MakeFrameBufferUpdate(
    const StripePtrVec& stripes) {
  return use_jpeg_compression_ ? MakeJpegFrameBufferUpdate(stripes)
                               : MakeRawFrameBufferUpdate(stripes);
}

void VncClientConnection::FrameBufferUpdateRequestHandler(bool aggressive) {
  BlackBoard::Registerer reg(bb_, this);
  const StripeSeqNumber kBeginningOfTime{};

  while (!closed()) {
    auto stripes = bb_->WaitForSenderWork(this);
    if (closed()) {
      break;
    }
    if (stripes.empty()) {
      LOG(FATAL) << "Got 0 stripes";
    }
    {
      // lock here so a portrait frame can't be sent after a landscape
      // DesktopSize update, or vice versa.
      std::lock_guard<std::mutex> guard(m_);
      DLOG(INFO) << "Sending update in "
                 << (current_orientation_ == ScreenOrientation::Portrait
                         ? "portrait"
                         : "landscape")
                 << " mode";
      client_.Send(MakeFrameBufferUpdate(stripes));
    }
    if (aggressive) {
      bb_->FrameBufferUpdateRequestReceived(this);
    }
  }
}

void VncClientConnection::SendDesktopSizeUpdate() {
  static constexpr int32_t kDesktopSizeEncoding = -223;
  client_.Send(CreateMessage(std::uint8_t{0},   // message-type,
                             std::uint8_t{},    // padding
                             std::uint16_t{1},  // one pseudo rectangle
                             std::uint16_t{0}, std::uint16_t{0},
                             static_cast<std::uint16_t>(ScreenWidth()),
                             static_cast<std::uint16_t>(ScreenHeight()),
                             kDesktopSizeEncoding));
}

bool VncClientConnection::IsUrgent(
    const FrameBufferUpdateRequest& update_request) const {
  return !update_request.incremental ||
         update_request != previous_update_request_;
}

void VncClientConnection::HandleFramebufferUpdateRequest() {
  auto msg = client_.Recv(kFramebufferUpdateRequestLength);
  if (msg.size() != kFramebufferUpdateRequestLength) {
    return;
  }
  FrameBufferUpdateRequest fbur{msg[1] == 0, uint16_tAt(&msg[1]),
                                uint16_tAt(&msg[3]), uint16_tAt(&msg[5]),
                                uint16_tAt(&msg[7])};
  if (IsUrgent(fbur)) {
    bb_->SignalClientNeedsEntireScreen(this);
  }
  bb_->FrameBufferUpdateRequestReceived(this);
  previous_update_request_ = fbur;
}

void VncClientConnection::HandleSetEncodings() {
  auto msg = client_.Recv(kSetEncodingsLength);
  if (msg.size() != kSetEncodingsLength) {
    return;
  }
  auto count = uint16_tAt(&msg[1]);
  auto encodings = client_.Recv(count * sizeof(int32_t));
  if (encodings.size() % sizeof(int32_t) != 0) {
    return;
  }
  {
    std::lock_guard<std::mutex> guard(m_);
    use_jpeg_compression_ = false;
  }
  for (size_t i = 0; i < encodings.size(); i += sizeof(int32_t)) {
    auto enc = int32_tAt(&encodings[i]);
    DLOG(INFO) << "client requesting encoding: " << enc;
    if (enc == kTightEncoding) {
      // This is a deviation from the spec which says that if a jpeg quality
      // level is not specified, tight encoding won't use jpeg.
      std::lock_guard<std::mutex> guard(m_);
      use_jpeg_compression_ = true;
    }
    if (kJpegMinQualityEncoding <= enc && enc <= kJpegMaxQualityEncoding) {
      DLOG(INFO) << "jpeg compression level: " << enc;
      bb_->set_jpeg_quality_level(enc);
    }
    if (enc == kDesktopSizeEncoding) {
      supports_desktop_size_encoding_ = true;
    }
  }
}

void VncClientConnection::HandleSetPixelFormat() {
  std::lock_guard<std::mutex> guard(m_);
  auto msg = client_.Recv(kSetPixelFormatLength);
  if (msg.size() != kSetPixelFormatLength) {
    return;
  }
  pixel_format_.bits_per_pixel = msg[3];
  pixel_format_.depth = msg[4];
  pixel_format_.big_endian = msg[5];
  pixel_format_.true_color = msg[7];
  pixel_format_.red_max = uint16_tAt(&msg[8]);
  pixel_format_.green_max = uint16_tAt(&msg[10]);
  pixel_format_.blue_max = uint16_tAt(&msg[12]);
  pixel_format_.red_shift = msg[13];
  pixel_format_.green_shift = msg[14];
  pixel_format_.blue_shift = msg[15];
}

void VncClientConnection::HandlePointerEvent() {
  auto msg = client_.Recv(kPointerEventLength);
  if (msg.size() != kPointerEventLength) {
    return;
  }
  std::uint8_t button_mask = msg[0];
  auto x_pos = uint16_tAt(&msg[1]);
  auto y_pos = uint16_tAt(&msg[3]);
  {
    std::lock_guard<std::mutex> guard(m_);
    if (current_orientation_ == ScreenOrientation::Landscape) {
      std::tie(x_pos, y_pos) =
          std::make_pair(ActualScreenWidth() - y_pos, x_pos);
    }
  }
  virtual_inputs_->HandlePointerEvent(button_mask, x_pos, y_pos);
}

void VncClientConnection::UpdateAccelerometer(float x, float y, float z) {
  // // Discard the event if we don't have a connection to the HAL.
  // if (!sensor_event_hal_->IsOpen()) {
  //   LOG(ERROR) << "sensor event client not open";
  //   return;
  // }
  // timespec current_time{};
  // clock_gettime(CLOCK_MONOTONIC, &current_time);
  // // Construct the sensor message.
  // gce_sensors_message message{};
  // message.version = sizeof message;
  // message.sensor = cvd::sensors_constants::kAccelerometerHandle;
  // message.type = SENSOR_TYPE_ACCELEROMETER;
  // message.timestamp = current_time.tv_sec * static_cast<int64_t>(1000000000)
  // +
  //                     current_time.tv_nsec;
  // message.data[0] = x;
  // message.data[1] = y;
  // message.data[2] = z;

  // std::array<iovec, 1> msg_iov{};
  // msg_iov[0].iov_base = &message;
  // msg_iov[0].iov_len = sizeof(sensors_event_t);

  // msghdr msg;
  // msg.msg_name = nullptr;
  // msg.msg_namelen = 0;
  // msg.msg_iov = msg_iov.data();
  // msg.msg_iovlen = msg_iov.size();
  // msg.msg_control = nullptr;
  // msg.msg_controllen = 0;
  // msg.msg_flags = 0;
  // if (sensor_event_hal_->SendMsg(&msg, 0) == -1) {
  //   LOG(ERROR) << __FUNCTION__ << ": Could not send sensor data. (%s)." <<
  //         sensor_event_hal_->StrError();
  // }
}

VncClientConnection::Coordinates VncClientConnection::CoordinatesForOrientation(
    ScreenOrientation orientation) const {
  // Compute the acceleration vector that we need to send to mimic
  // this change.
  constexpr float g = 9.81;
  constexpr float angle = 20.0;
  const float cos_angle = std::cos(angle / M_PI);
  const float sin_angle = std::sin(angle / M_PI);
  const float z = g * sin_angle;
  switch (orientation) {
    case ScreenOrientation::Portrait:
      return {0, g * cos_angle, z};
    case ScreenOrientation::Landscape:
      return {g * cos_angle, 0, z};
  }
}

int VncClientConnection::ScreenWidth() const {
  return current_orientation_ == ScreenOrientation::Portrait
             ? ActualScreenWidth()
             : ActualScreenHeight();
}

int VncClientConnection::ScreenHeight() const {
  return current_orientation_ == ScreenOrientation::Portrait
             ? ActualScreenHeight()
             : ActualScreenWidth();
}

void VncClientConnection::SetScreenOrientation(ScreenOrientation orientation) {
  std::lock_guard<std::mutex> guard(m_);
  auto coords = CoordinatesForOrientation(orientation);
  UpdateAccelerometer(coords.x, coords.y, coords.z);
  if (supports_desktop_size_encoding_) {
    auto previous_orientation = current_orientation_;
    current_orientation_ = orientation;
    if (current_orientation_ != previous_orientation &&
        supports_desktop_size_encoding_) {
      SendDesktopSizeUpdate();
      bb_->SetOrientation(this, current_orientation_);
      // TODO not sure if I should be sending a frame update along with this,
      // or just letting the next FBUR handle it. This seems to me like it's
      // sending one more frame buffer update than was requested, which is
      // maybe a violation of the spec?
    }
  }
}

bool VncClientConnection::RotateIfIsRotationCommand(std::uint32_t key) {
  // Due to different configurations on different platforms we're supporting
  // a set of options for rotating the screen. These are similar to what
  // the emulator supports and has supported.
  // ctrl+left and ctrl+right work on windows and linux
  // command+left and command+right work on Mac
  // ctrl+fn+F11 and ctrl+fn+F12 work when chromoting to ubuntu from a Mac
  if (!control_key_down_ && !meta_key_down_) {
    return false;
  }
  switch (key) {
    case cvd::xk::Right:
    case cvd::xk::F12:
      DLOG(INFO) << "switching to portrait";
      SetScreenOrientation(ScreenOrientation::Portrait);
      break;
    case cvd::xk::Left:
    case cvd::xk::F11:
      DLOG(INFO) << "switching to landscape";
      SetScreenOrientation(ScreenOrientation::Landscape);
      break;
    default:
      return false;
  }
  return true;
}

void VncClientConnection::HandleKeyEvent() {
  auto msg = client_.Recv(kKeyEventLength);
  if (msg.size() != kKeyEventLength) {
    return;
  }

  auto key = uint32_tAt(&msg[3]);
  bool key_down = msg[0];
  switch (key) {
    case cvd::xk::ControlLeft:
    case cvd::xk::ControlRight:
      control_key_down_ = key_down;
      break;
    case cvd::xk::MetaLeft:
    case cvd::xk::MetaRight:
      meta_key_down_ = key_down;
      break;
    case cvd::xk::F5:
      key = cvd::xk::Menu;
      break;
    case cvd::xk::F7:
      virtual_inputs_->PressPowerButton(key_down);
      return;
    default:
      break;
  }

  if (RotateIfIsRotationCommand(key)) {
    return;
  }

  virtual_inputs_->GenerateKeyPressEvent(key, key_down);
}

void VncClientConnection::HandleClientCutText() {
  auto msg = client_.Recv(kClientCutTextLength);
  if (msg.size() != kClientCutTextLength) {
    return;
  }
  auto len = uint32_tAt(&msg[3]);
  client_.Recv(len);
}

void VncClientConnection::NormalSession() {
  static constexpr std::uint8_t kSetPixelFormatMessage{0};
  static constexpr std::uint8_t kSetEncodingsMessage{2};
  static constexpr std::uint8_t kFramebufferUpdateRequestMessage{3};
  static constexpr std::uint8_t kKeyEventMessage{4};
  static constexpr std::uint8_t kPointerEventMessage{5};
  static constexpr std::uint8_t kClientCutTextMessage{6};
  while (true) {
    if (client_.closed()) {
      return;
    }
    auto msg = client_.Recv(1);
    if (client_.closed()) {
      return;
    }
    auto msg_type = msg.front();
    DLOG(INFO) << "Received message type " << msg_type;

    switch (msg_type) {
      case kSetPixelFormatMessage:
        HandleSetPixelFormat();
        break;

      case kSetEncodingsMessage:
        HandleSetEncodings();
        break;

      case kFramebufferUpdateRequestMessage:
        HandleFramebufferUpdateRequest();
        break;

      case kKeyEventMessage:
        HandleKeyEvent();
        break;

      case kPointerEventMessage:
        HandlePointerEvent();
        break;

      case kClientCutTextMessage:
        HandleClientCutText();
        break;

      default:
        LOG(WARNING) << "message type not handled: "
                     << static_cast<int>(msg_type);
        break;
    }
  }
}
