// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/protocol/client_control_dispatcher.h"

#include <stdint.h>

#include "base/bind_helpers.h"
#include "base/callback.h"
#include "net/socket/stream_socket.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/base/constants.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/internal.pb.h"
#include "remoting/protocol/client_stub.h"
#include "remoting/protocol/message_pipe.h"
#include "remoting/protocol/message_serialization.h"

namespace remoting {
namespace protocol {

namespace {

// 32-bit BGRA is 4 bytes per pixel.
const int kBytesPerPixel = 4;

bool CursorShapeIsValid(const CursorShapeInfo& cursor_shape) {
  if (!cursor_shape.has_data() ||
      !cursor_shape.has_width() ||
      !cursor_shape.has_height() ||
      !cursor_shape.has_hotspot_x() ||
      !cursor_shape.has_hotspot_y()) {
    LOG(ERROR) << "Cursor shape is missing required fields.";
    return false;
  }

  int width = cursor_shape.width();
  int height = cursor_shape.height();

  // Verify that |width| and |height| are within sane limits. Otherwise integer
  // overflow can occur while calculating |cursor_total_bytes| below.
  if (width < 0 || width > (SHRT_MAX / 2) ||
      height < 0 || height > (SHRT_MAX / 2)) {
    LOG(ERROR) << "Cursor dimensions are out of bounds for SetCursor: "
               << width << "x" << height;
    return false;
  }

  uint32_t cursor_total_bytes = width * height * kBytesPerPixel;
  if (cursor_shape.data().size() < cursor_total_bytes) {
    LOG(ERROR) << "Expected " << cursor_total_bytes << " bytes for a "
               << width << "x" << height << " cursor. Only received "
               << cursor_shape.data().size() << " bytes";
    return false;
  }

  return true;
}

}  // namespace

ClientControlDispatcher::ClientControlDispatcher()
    : ChannelDispatcherBase(kControlChannelName) {}
ClientControlDispatcher::~ClientControlDispatcher() {}

void ClientControlDispatcher::InjectClipboardEvent(
    const ClipboardEvent& event) {
  ControlMessage message;
  message.mutable_clipboard_event()->CopyFrom(event);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::NotifyClientResolution(
    const ClientResolution& resolution) {
  ControlMessage message;
  message.mutable_client_resolution()->CopyFrom(resolution);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::ControlVideo(const VideoControl& video_control) {
  ControlMessage message;
  message.mutable_video_control()->CopyFrom(video_control);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::ControlAudio(const AudioControl& audio_control) {
  ControlMessage message;
  message.mutable_audio_control()->CopyFrom(audio_control);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::SetCapabilities(
    const Capabilities& capabilities) {
  ControlMessage message;
  message.mutable_capabilities()->CopyFrom(capabilities);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::RequestPairing(
    const PairingRequest& pairing_request) {
  ControlMessage message;
  message.mutable_pairing_request()->CopyFrom(pairing_request);
  message_pipe()->Send(&message, base::Closure());
}

void ClientControlDispatcher::DeliverClientMessage(
    const ExtensionMessage& message) {
  ControlMessage control_message;
  control_message.mutable_extension_message()->CopyFrom(message);
  message_pipe()->Send(&control_message, base::Closure());
}

void ClientControlDispatcher::OnIncomingMessage(
    std::unique_ptr<CompoundBuffer> buffer) {
  DCHECK(client_stub_);
  DCHECK(clipboard_stub_);

  std::unique_ptr<ControlMessage> message =
      ParseMessage<ControlMessage>(buffer.get());
  if (!message)
    return;

  if (message->has_clipboard_event()) {
    clipboard_stub_->InjectClipboardEvent(message->clipboard_event());
  } else if (message->has_capabilities()) {
    client_stub_->SetCapabilities(message->capabilities());
  } else if (message->has_cursor_shape()) {
    if (CursorShapeIsValid(message->cursor_shape()))
      client_stub_->SetCursorShape(message->cursor_shape());
  } else if (message->has_pairing_response()) {
    client_stub_->SetPairingResponse(message->pairing_response());
  } else if (message->has_extension_message()) {
    client_stub_->DeliverHostMessage(message->extension_message());
  } else if (message->has_video_layout()) {
    client_stub_->SetVideoLayout(message->video_layout());
  } else {
    LOG(WARNING) << "Unknown control message received.";
  }
}

}  // namespace protocol
}  // namespace remoting
