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 <stdint.h> 8 9 #include "base/callback.h" 10 #include "base/callback_helpers.h" 11 #include "net/socket/stream_socket.h" 12 #include "remoting/base/compound_buffer.h" 13 #include "remoting/base/constants.h" 14 #include "remoting/proto/control.pb.h" 15 #include "remoting/proto/internal.pb.h" 16 #include "remoting/protocol/client_stub.h" 17 #include "remoting/protocol/message_pipe.h" 18 #include "remoting/protocol/message_serialization.h" 19 20 namespace remoting { 21 namespace protocol { 22 23 namespace { 24 25 // 32-bit BGRA is 4 bytes per pixel. 26 const int kBytesPerPixel = 4; 27 CursorShapeIsValid(const CursorShapeInfo & cursor_shape)28bool CursorShapeIsValid(const CursorShapeInfo& cursor_shape) { 29 if (!cursor_shape.has_data() || 30 !cursor_shape.has_width() || 31 !cursor_shape.has_height() || 32 !cursor_shape.has_hotspot_x() || 33 !cursor_shape.has_hotspot_y()) { 34 LOG(ERROR) << "Cursor shape is missing required fields."; 35 return false; 36 } 37 38 int width = cursor_shape.width(); 39 int height = cursor_shape.height(); 40 41 // Verify that |width| and |height| are within sane limits. Otherwise integer 42 // overflow can occur while calculating |cursor_total_bytes| below. 43 if (width < 0 || width > (SHRT_MAX / 2) || 44 height < 0 || height > (SHRT_MAX / 2)) { 45 LOG(ERROR) << "Cursor dimensions are out of bounds for SetCursor: " 46 << width << "x" << height; 47 return false; 48 } 49 50 uint32_t cursor_total_bytes = width * height * kBytesPerPixel; 51 if (cursor_shape.data().size() < cursor_total_bytes) { 52 LOG(ERROR) << "Expected " << cursor_total_bytes << " bytes for a " 53 << width << "x" << height << " cursor. Only received " 54 << cursor_shape.data().size() << " bytes"; 55 return false; 56 } 57 58 return true; 59 } 60 61 } // namespace 62 ClientControlDispatcher()63ClientControlDispatcher::ClientControlDispatcher() 64 : ChannelDispatcherBase(kControlChannelName) {} 65 ClientControlDispatcher::~ClientControlDispatcher() = default; 66 InjectClipboardEvent(const ClipboardEvent & event)67void ClientControlDispatcher::InjectClipboardEvent( 68 const ClipboardEvent& event) { 69 ControlMessage message; 70 message.mutable_clipboard_event()->CopyFrom(event); 71 message_pipe()->Send(&message, {}); 72 } 73 NotifyClientResolution(const ClientResolution & resolution)74void ClientControlDispatcher::NotifyClientResolution( 75 const ClientResolution& resolution) { 76 ControlMessage message; 77 message.mutable_client_resolution()->CopyFrom(resolution); 78 message_pipe()->Send(&message, {}); 79 } 80 ControlVideo(const VideoControl & video_control)81void ClientControlDispatcher::ControlVideo(const VideoControl& video_control) { 82 ControlMessage message; 83 message.mutable_video_control()->CopyFrom(video_control); 84 message_pipe()->Send(&message, {}); 85 } 86 ControlAudio(const AudioControl & audio_control)87void ClientControlDispatcher::ControlAudio(const AudioControl& audio_control) { 88 ControlMessage message; 89 message.mutable_audio_control()->CopyFrom(audio_control); 90 message_pipe()->Send(&message, {}); 91 } 92 SetCapabilities(const Capabilities & capabilities)93void ClientControlDispatcher::SetCapabilities( 94 const Capabilities& capabilities) { 95 ControlMessage message; 96 message.mutable_capabilities()->CopyFrom(capabilities); 97 message_pipe()->Send(&message, {}); 98 } 99 RequestPairing(const PairingRequest & pairing_request)100void ClientControlDispatcher::RequestPairing( 101 const PairingRequest& pairing_request) { 102 ControlMessage message; 103 message.mutable_pairing_request()->CopyFrom(pairing_request); 104 message_pipe()->Send(&message, {}); 105 } 106 DeliverClientMessage(const ExtensionMessage & message)107void ClientControlDispatcher::DeliverClientMessage( 108 const ExtensionMessage& message) { 109 ControlMessage control_message; 110 control_message.mutable_extension_message()->CopyFrom(message); 111 message_pipe()->Send(&control_message, {}); 112 } 113 SelectDesktopDisplay(const SelectDesktopDisplayRequest & select_display)114void ClientControlDispatcher::SelectDesktopDisplay( 115 const SelectDesktopDisplayRequest& select_display) { 116 ControlMessage message; 117 message.mutable_select_display()->CopyFrom(select_display); 118 message_pipe()->Send(&message, {}); 119 } 120 ControlPeerConnection(const protocol::PeerConnectionParameters & parameters)121void ClientControlDispatcher::ControlPeerConnection( 122 const protocol::PeerConnectionParameters& parameters) { 123 ControlMessage message; 124 message.mutable_peer_connection_parameters()->CopyFrom(parameters); 125 message_pipe()->Send(&message, {}); 126 } 127 OnIncomingMessage(std::unique_ptr<CompoundBuffer> buffer)128void ClientControlDispatcher::OnIncomingMessage( 129 std::unique_ptr<CompoundBuffer> buffer) { 130 DCHECK(client_stub_); 131 DCHECK(clipboard_stub_); 132 133 std::unique_ptr<ControlMessage> message = 134 ParseMessage<ControlMessage>(buffer.get()); 135 if (!message) 136 return; 137 138 if (message->has_clipboard_event()) { 139 clipboard_stub_->InjectClipboardEvent(message->clipboard_event()); 140 } else if (message->has_capabilities()) { 141 client_stub_->SetCapabilities(message->capabilities()); 142 } else if (message->has_cursor_shape()) { 143 if (CursorShapeIsValid(message->cursor_shape())) 144 client_stub_->SetCursorShape(message->cursor_shape()); 145 } else if (message->has_pairing_response()) { 146 client_stub_->SetPairingResponse(message->pairing_response()); 147 } else if (message->has_extension_message()) { 148 client_stub_->DeliverHostMessage(message->extension_message()); 149 } else if (message->has_video_layout()) { 150 client_stub_->SetVideoLayout(message->video_layout()); 151 } else { 152 LOG(WARNING) << "Unknown control message received."; 153 } 154 } 155 156 } // namespace protocol 157 } // namespace remoting 158