// Copyright (c) 2010 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 "base/ref_counted.h" #include "net/base/io_buffer.h" #include "remoting/proto/control.pb.h" #include "remoting/proto/event.pb.h" #include "remoting/proto/internal.pb.h" #include "remoting/protocol/host_message_dispatcher.h" #include "remoting/protocol/host_stub.h" #include "remoting/protocol/input_stub.h" #include "remoting/protocol/message_reader.h" #include "remoting/protocol/session.h" namespace { // A single protobuf can contain multiple messages that will be handled by // different message handlers. We use this wrapper to ensure that the // protobuf is only deleted after all the handlers have finished executing. template class RefCountedMessage : public base::RefCounted > { public: RefCountedMessage(T* message) : message_(message) { } T* message() { return message_.get(); } private: scoped_ptr message_; }; // Dummy methods to destroy messages. template static void DeleteMessage(scoped_refptr message) { } template static Task* NewDeleteTask(scoped_refptr message) { return NewRunnableFunction(&DeleteMessage, message); } } // namespace namespace remoting { namespace protocol { HostMessageDispatcher::HostMessageDispatcher() : host_stub_(NULL), input_stub_(NULL) { } HostMessageDispatcher::~HostMessageDispatcher() { } bool HostMessageDispatcher::Initialize( protocol::Session* session, HostStub* host_stub, InputStub* input_stub) { if (!session || !host_stub || !input_stub || !session->event_channel() || !session->control_channel()) { return false; } control_message_reader_.reset(new MessageReader()); event_message_reader_.reset(new MessageReader()); host_stub_ = host_stub; input_stub_ = input_stub; // Initialize the readers on the sockets provided by channels. event_message_reader_->Init( session->event_channel(), NewCallback(this, &HostMessageDispatcher::OnEventMessageReceived)); control_message_reader_->Init( session->control_channel(), NewCallback(this, &HostMessageDispatcher::OnControlMessageReceived)); return true; } void HostMessageDispatcher::OnControlMessageReceived(ControlMessage* message) { scoped_refptr > ref_msg = new RefCountedMessage(message); if (message->has_suggest_resolution()) { host_stub_->SuggestResolution( &message->suggest_resolution(), NewDeleteTask(ref_msg)); } } void HostMessageDispatcher::OnEventMessageReceived( EventMessage* message) { scoped_refptr > ref_msg = new RefCountedMessage(message); for (int i = 0; i < message->event_size(); ++i) { if (message->event(i).has_key()) { input_stub_->InjectKeyEvent( &message->event(i).key(), NewDeleteTask(ref_msg)); } if (message->event(i).has_mouse()) { input_stub_->InjectMouseEvent( &message->event(i).mouse(), NewDeleteTask(ref_msg)); } } } } // namespace protocol } // namespace remoting