blob: 599c779fbae4a3e4ea21f86e41c24a23d99221db [file] [log] [blame]
[email protected]e265ad72012-03-16 17:28:031// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]409ac612011-11-18 04:05:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/protocol/client_control_dispatcher.h"
6
[email protected]c6944272012-01-06 22:12:287#include "base/bind_helpers.h"
8#include "base/callback.h"
[email protected]1c232c22013-08-30 02:04:049#include "base/callback_helpers.h"
[email protected]7ccb7072013-06-10 20:56:2810#include "base/message_loop/message_loop_proxy.h"
[email protected]2e8b52c2011-11-22 00:07:1311#include "net/socket/stream_socket.h"
12#include "remoting/base/constants.h"
[email protected]409ac612011-11-18 04:05:5713#include "remoting/proto/control.pb.h"
[email protected]409ac612011-11-18 04:05:5714#include "remoting/proto/internal.pb.h"
15#include "remoting/protocol/client_stub.h"
[email protected]b76a2742014-04-10 05:38:2616#include "remoting/protocol/message_serialization.h"
[email protected]409ac612011-11-18 04:05:5717
18namespace remoting {
19namespace protocol {
20
[email protected]cb959342013-09-12 05:39:0221namespace {
22
23// 32-bit BGRA is 4 bytes per pixel.
24const int kBytesPerPixel = 4;
25
26bool CursorShapeIsValid(const CursorShapeInfo& cursor_shape) {
27 if (!cursor_shape.has_data() ||
28 !cursor_shape.has_width() ||
29 !cursor_shape.has_height() ||
30 !cursor_shape.has_hotspot_x() ||
31 !cursor_shape.has_hotspot_y()) {
32 LOG(ERROR) << "Cursor shape is missing required fields.";
33 return false;
34 }
35
36 int width = cursor_shape.width();
37 int height = cursor_shape.height();
38
39 // Verify that |width| and |height| are within sane limits. Otherwise integer
40 // overflow can occur while calculating |cursor_total_bytes| below.
41 if (width <= 0 || width > (SHRT_MAX / 2) ||
42 height <= 0 || height > (SHRT_MAX / 2)) {
43 LOG(ERROR) << "Cursor dimensions are out of bounds for SetCursor: "
44 << width << "x" << height;
45 return false;
46 }
47
48 uint32 cursor_total_bytes = width * height * kBytesPerPixel;
49 if (cursor_shape.data().size() < cursor_total_bytes) {
50 LOG(ERROR) << "Expected " << cursor_total_bytes << " bytes for a "
51 << width << "x" << height << " cursor. Only received "
52 << cursor_shape.data().size() << " bytes";
53 return false;
54 }
55
56 return true;
57}
58
59} // namespace
60
[email protected]409ac612011-11-18 04:05:5761ClientControlDispatcher::ClientControlDispatcher()
[email protected]2e8b52c2011-11-22 00:07:1362 : ChannelDispatcherBase(kControlChannelName),
63 client_stub_(NULL),
[email protected]a3464dca2012-05-24 01:27:0964 clipboard_stub_(NULL) {
[email protected]409ac612011-11-18 04:05:5765}
66
67ClientControlDispatcher::~ClientControlDispatcher() {
[email protected]a3464dca2012-05-24 01:27:0968 writer_.Close();
[email protected]409ac612011-11-18 04:05:5769}
70
[email protected]2e8b52c2011-11-22 00:07:1371void ClientControlDispatcher::OnInitialized() {
[email protected]409ac612011-11-18 04:05:5772 // TODO(garykac): Set write failed callback.
[email protected]a3464dca2012-05-24 01:27:0973 writer_.Init(channel(), BufferedSocketWriter::WriteFailedCallback());
[email protected]2e8b52c2011-11-22 00:07:1374 reader_.Init(channel(), base::Bind(
[email protected]409ac612011-11-18 04:05:5775 &ClientControlDispatcher::OnMessageReceived, base::Unretained(this)));
76}
77
[email protected]e265ad72012-03-16 17:28:0378void ClientControlDispatcher::InjectClipboardEvent(
79 const ClipboardEvent& event) {
80 ControlMessage message;
81 message.mutable_clipboard_event()->CopyFrom(event);
[email protected]a3464dca2012-05-24 01:27:0982 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
[email protected]e265ad72012-03-16 17:28:0383}
84
[email protected]48a8ca32013-02-13 04:31:0185void ClientControlDispatcher::NotifyClientResolution(
86 const ClientResolution& resolution) {
[email protected]f2b9cf32012-04-27 00:13:4387 ControlMessage message;
[email protected]48a8ca32013-02-13 04:31:0188 message.mutable_client_resolution()->CopyFrom(resolution);
[email protected]a3464dca2012-05-24 01:27:0989 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
[email protected]f2b9cf32012-04-27 00:13:4390}
91
[email protected]50d71c72012-05-03 01:28:5592void ClientControlDispatcher::ControlVideo(const VideoControl& video_control) {
93 ControlMessage message;
94 message.mutable_video_control()->CopyFrom(video_control);
[email protected]a3464dca2012-05-24 01:27:0995 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
[email protected]50d71c72012-05-03 01:28:5596}
97
[email protected]f458bed2012-10-18 03:27:5998void ClientControlDispatcher::ControlAudio(const AudioControl& audio_control) {
99 ControlMessage message;
100 message.mutable_audio_control()->CopyFrom(audio_control);
101 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
102}
103
[email protected]a5d181f2013-04-19 14:55:37104void ClientControlDispatcher::SetCapabilities(
105 const Capabilities& capabilities) {
106 ControlMessage message;
107 message.mutable_capabilities()->CopyFrom(capabilities);
108 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
109}
110
[email protected]9ffa78a22013-05-10 04:35:10111void ClientControlDispatcher::RequestPairing(
112 const PairingRequest& pairing_request) {
113 ControlMessage message;
114 message.mutable_pairing_request()->CopyFrom(pairing_request);
115 writer_.Write(SerializeAndFrameMessage(message), base::Closure());
116}
117
[email protected]09eabd65c2013-08-13 00:13:48118void ClientControlDispatcher::DeliverClientMessage(
119 const ExtensionMessage& message) {
120 ControlMessage control_message;
121 control_message.mutable_extension_message()->CopyFrom(message);
122 writer_.Write(SerializeAndFrameMessage(control_message), base::Closure());
123}
124
[email protected]409ac612011-11-18 04:05:57125void ClientControlDispatcher::OnMessageReceived(
[email protected]9302fce2012-03-28 03:57:57126 scoped_ptr<ControlMessage> message, const base::Closure& done_task) {
[email protected]409ac612011-11-18 04:05:57127 DCHECK(client_stub_);
[email protected]ba6d1c2d2012-03-31 01:28:38128 DCHECK(clipboard_stub_);
[email protected]409ac612011-11-18 04:05:57129 base::ScopedClosureRunner done_runner(done_task);
[email protected]ba6d1c2d2012-03-31 01:28:38130
131 if (message->has_clipboard_event()) {
132 clipboard_stub_->InjectClipboardEvent(message->clipboard_event());
[email protected]a5d181f2013-04-19 14:55:37133 } else if (message->has_capabilities()) {
134 client_stub_->SetCapabilities(message->capabilities());
[email protected]d65e15bd2012-06-02 22:16:41135 } else if (message->has_cursor_shape()) {
[email protected]cb959342013-09-12 05:39:02136 if (CursorShapeIsValid(message->cursor_shape()))
137 client_stub_->SetCursorShape(message->cursor_shape());
[email protected]9ffa78a22013-05-10 04:35:10138 } else if (message->has_pairing_response()) {
139 client_stub_->SetPairingResponse(message->pairing_response());
[email protected]09eabd65c2013-08-13 00:13:48140 } else if (message->has_extension_message()) {
141 client_stub_->DeliverHostMessage(message->extension_message());
[email protected]ba6d1c2d2012-03-31 01:28:38142 } else {
143 LOG(WARNING) << "Unknown control message received.";
144 }
[email protected]409ac612011-11-18 04:05:57145}
146
147} // namespace protocol
148} // namespace remoting