1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // 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 7 #include "base/bind_helpers.h" 8 #include "base/callback.h" 9 #include "base/callback_helpers.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "net/socket/stream_socket.h" 12 #include "remoting/base/constants.h" 13 #include "remoting/proto/control.pb.h" 14 #include "remoting/proto/internal.pb.h" 15 #include "remoting/protocol/client_stub.h" 16 #include "remoting/protocol/message_serialization.h" 17 18 namespace remoting { 19 namespace protocol { 20 21 namespace { 22 23 // 32-bit BGRA is 4 bytes per pixel. 24 const int kBytesPerPixel = 4; 25 26 bool 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 61 ClientControlDispatcher::ClientControlDispatcher() 62 : ChannelDispatcherBase(kControlChannelName), 63 client_stub_(NULL), 64 clipboard_stub_(NULL) { 65 } 66 67 ClientControlDispatcher::~ClientControlDispatcher() { 68 writer_.Close(); 69 } 70 71 void ClientControlDispatcher::OnInitialized() { 72 // TODO(garykac): Set write failed callback. 73 writer_.Init(channel(), BufferedSocketWriter::WriteFailedCallback()); 74 reader_.Init(channel(), base::Bind( 75 &ClientControlDispatcher::OnMessageReceived, base::Unretained(this))); 76 } 77 78 void ClientControlDispatcher::InjectClipboardEvent( 79 const ClipboardEvent& event) { 80 ControlMessage message; 81 message.mutable_clipboard_event()->CopyFrom(event); 82 writer_.Write(SerializeAndFrameMessage(message), base::Closure()); 83 } 84 85 void ClientControlDispatcher::NotifyClientResolution( 86 const ClientResolution& resolution) { 87 ControlMessage message; 88 message.mutable_client_resolution()->CopyFrom(resolution); 89 writer_.Write(SerializeAndFrameMessage(message), base::Closure()); 90 } 91 92 void ClientControlDispatcher::ControlVideo(const VideoControl& video_control) { 93 ControlMessage message; 94 message.mutable_video_control()->CopyFrom(video_control); 95 writer_.Write(SerializeAndFrameMessage(message), base::Closure()); 96 } 97 98 void 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 104 void ClientControlDispatcher::SetCapabilities( 105 const Capabilities& capabilities) { 106 ControlMessage message; 107 message.mutable_capabilities()->CopyFrom(capabilities); 108 writer_.Write(SerializeAndFrameMessage(message), base::Closure()); 109 } 110 111 void 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 118 void 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 125 void ClientControlDispatcher::OnMessageReceived( 126 scoped_ptr<ControlMessage> message, const base::Closure& done_task) { 127 DCHECK(client_stub_); 128 DCHECK(clipboard_stub_); 129 base::ScopedClosureRunner done_runner(done_task); 130 131 if (message->has_clipboard_event()) { 132 clipboard_stub_->InjectClipboardEvent(message->clipboard_event()); 133 } else if (message->has_capabilities()) { 134 client_stub_->SetCapabilities(message->capabilities()); 135 } else if (message->has_cursor_shape()) { 136 if (CursorShapeIsValid(message->cursor_shape())) 137 client_stub_->SetCursorShape(message->cursor_shape()); 138 } else if (message->has_pairing_response()) { 139 client_stub_->SetPairingResponse(message->pairing_response()); 140 } else if (message->has_extension_message()) { 141 client_stub_->DeliverHostMessage(message->extension_message()); 142 } else { 143 LOG(WARNING) << "Unknown control message received."; 144 } 145 } 146 147 } // namespace protocol 148 } // namespace remoting 149