diff options
-rw-r--r-- | remoting/client/chromoting_client.cc | 85 | ||||
-rw-r--r-- | remoting/client/chromoting_client.h | 14 | ||||
-rw-r--r-- | remoting/client/chromoting_view.h | 12 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 12 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.cc | 42 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.h | 59 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view.cc | 59 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view.h | 8 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view_proxy.cc | 8 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view_proxy.h | 4 | ||||
-rw-r--r-- | remoting/protocol/connection_to_host.cc | 74 | ||||
-rw-r--r-- | remoting/protocol/connection_to_host.h | 33 | ||||
-rw-r--r-- | remoting/protocol/session.h | 4 |
13 files changed, 225 insertions, 189 deletions
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc index 71a611a..22569625 100644 --- a/remoting/client/chromoting_client.cc +++ b/remoting/client/chromoting_client.cc @@ -5,7 +5,6 @@ #include "remoting/client/chromoting_client.h" #include "base/bind.h" -#include "jingle/glue/thread_wrapper.h" #include "remoting/client/chromoting_view.h" #include "remoting/client/client_context.h" #include "remoting/client/input_handler.h" @@ -29,23 +28,16 @@ ChromotingClient::ChromotingClient(const ClientConfig& config, rectangle_decoder_(rectangle_decoder), input_handler_(input_handler), client_done_(client_done), - state_(CREATED), packet_being_processed_(false), - last_sequence_number_(0) { + last_sequence_number_(0), + thread_proxy_(context_->network_message_loop()) { } ChromotingClient::~ChromotingClient() { } void ChromotingClient::Start(scoped_refptr<XmppProxy> xmpp_proxy) { - if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::Start, xmpp_proxy)); - return; - } - - jingle_glue::JingleThreadWrapper::EnsureForCurrentThread(); + DCHECK(message_loop()->BelongsToCurrentThread()); connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, config_.host_public_key, config_.access_code, @@ -85,25 +77,13 @@ ChromotingStats* ChromotingClient::GetStats() { } void ChromotingClient::Repaint() { - if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::Repaint)); - return; - } - + DCHECK(message_loop()->BelongsToCurrentThread()); view_->Paint(); } void ChromotingClient::ProcessVideoPacket(const VideoPacket* packet, Task* done) { - if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::ProcessVideoPacket, - packet, done)); - return; - } + DCHECK(message_loop()->BelongsToCurrentThread()); // If the video packet is empty then drop it. Empty packets are used to // maintain activity on the network. @@ -162,47 +142,26 @@ void ChromotingClient::DispatchPacket() { last_packet, decode_start)); } -void ChromotingClient::OnConnectionOpened(protocol::ConnectionToHost* conn) { - VLOG(1) << "ChromotingClient::OnConnectionOpened"; - Initialize(); - SetConnectionState(CONNECTED); -} - -void ChromotingClient::OnConnectionClosed(protocol::ConnectionToHost* conn) { - VLOG(1) << "ChromotingClient::OnConnectionClosed"; - SetConnectionState(DISCONNECTED); -} - -void ChromotingClient::OnConnectionFailed(protocol::ConnectionToHost* conn) { - VLOG(1) << "ChromotingClient::OnConnectionFailed"; - SetConnectionState(FAILED); +void ChromotingClient::OnConnectionState( + protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) { + DCHECK(message_loop()->BelongsToCurrentThread()); + VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; + if (state == protocol::ConnectionToHost::CONNECTED) + Initialize(); + view_->SetConnectionState(state, error); } base::MessageLoopProxy* ChromotingClient::message_loop() { return context_->network_message_loop(); } -void ChromotingClient::SetConnectionState(ConnectionState s) { - // TODO(ajwong): We actually may want state to be a shared variable. Think - // through later. - if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::SetConnectionState, s)); - return; - } - - state_ = s; - view_->SetConnectionState(s); -} - void ChromotingClient::OnPacketDone(bool last_packet, base::Time decode_start) { if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::OnPacketDone, - last_packet, decode_start)); + thread_proxy_.PostTask(FROM_HERE, base::Bind( + &ChromotingClient::OnPacketDone, base::Unretained(this), + last_packet, decode_start)); return; } @@ -225,9 +184,8 @@ void ChromotingClient::OnPacketDone(bool last_packet, void ChromotingClient::Initialize() { if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::Initialize)); + thread_proxy_.PostTask(FROM_HERE, base::Bind( + &ChromotingClient::Initialize, base::Unretained(this))); return; } @@ -243,10 +201,9 @@ void ChromotingClient::Initialize() { void ChromotingClient::BeginSessionResponse( const protocol::LocalLoginStatus* msg, Task* done) { if (!message_loop()->BelongsToCurrentThread()) { - message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ChromotingClient::BeginSessionResponse, - msg, done)); + thread_proxy_.PostTask(FROM_HERE, base::Bind( + &ChromotingClient::BeginSessionResponse, base::Unretained(this), + msg, done)); return; } diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h index 0dfbb4c..5d18448 100644 --- a/remoting/client/chromoting_client.h +++ b/remoting/client/chromoting_client.h @@ -11,6 +11,7 @@ #include "base/task.h" #include "base/time.h" +#include "remoting/base/scoped_thread_proxy.h" #include "remoting/client/client_config.h" #include "remoting/client/chromoting_stats.h" #include "remoting/client/chromoting_view.h" @@ -59,9 +60,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, virtual void Repaint(); // ConnectionToHost::HostEventCallback implementation. - virtual void OnConnectionOpened(protocol::ConnectionToHost* conn) OVERRIDE; - virtual void OnConnectionClosed(protocol::ConnectionToHost* conn) OVERRIDE; - virtual void OnConnectionFailed(protocol::ConnectionToHost* conn) OVERRIDE; + virtual void OnConnectionState( + protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) OVERRIDE; // ClientStub implementation. virtual void BeginSessionResponse(const protocol::LocalLoginStatus* msg, @@ -86,9 +87,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, // Initializes connection. void Initialize(); - // Convenience method for modifying the state on this object's message loop. - void SetConnectionState(ConnectionState s); - // If a packet is not being processed, dispatches a single message from the // |received_packets_| queue. void DispatchPacket(); @@ -111,8 +109,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, // If non-NULL, this is called when the client is done. Task* client_done_; - ConnectionState state_; - // Contains all video packets that have been received, but have not yet been // processed. // @@ -129,6 +125,8 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, // Keep track of the last sequence number bounced back from the host. int64 last_sequence_number_; + ScopedThreadProxy thread_proxy_; + DISALLOW_COPY_AND_ASSIGN(ChromotingClient); }; diff --git a/remoting/client/chromoting_view.h b/remoting/client/chromoting_view.h index 6911489..c546513 100644 --- a/remoting/client/chromoting_view.h +++ b/remoting/client/chromoting_view.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "media/base/video_frame.h" +#include "remoting/protocol/connection_to_host.h" class MessageLoop; @@ -22,14 +23,6 @@ static const uint32 kCreatedColor = 0xffccccff; static const uint32 kDisconnectedColor = 0xff00ccff; static const uint32 kFailedColor = 0xffcc00ff; -// TODO(garykac): Move this into a proper class that keeps track of state. -enum ConnectionState { - CREATED, - CONNECTED, - DISCONNECTED, - FAILED, -}; - // ChromotingView defines the behavior of an object that draws a view of the // remote desktop. Its main function is to render the update stream onto the // screen. @@ -60,7 +53,8 @@ class ChromotingView { virtual void UnsetSolidFill() = 0; // Record the update the state of the connection, updating the UI as needed. - virtual void SetConnectionState(ConnectionState s) = 0; + virtual void SetConnectionState(protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) = 0; // Update the status of the last login attempt. Updating the UI as needed. // |success| is set to true if the last login successful otherwise false. diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index 1fc4573..60bd867 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -184,8 +184,9 @@ void ChromotingInstance::Connect(const ClientConfig& config) { client_->Start(xmpp_proxy); VLOG(1) << "Connection status: Initializing"; - GetScriptableObject()->SetConnectionInfo(STATUS_INITIALIZING, - QUALITY_UNKNOWN); + GetScriptableObject()->SetConnectionStatus( + ChromotingScriptableObject::STATUS_INITIALIZING, + ChromotingScriptableObject::ERROR_NONE); } void ChromotingInstance::Disconnect() { @@ -204,7 +205,9 @@ void ChromotingInstance::Disconnect() { input_handler_.reset(); host_connection_.reset(); - GetScriptableObject()->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN); + GetScriptableObject()->SetConnectionStatus( + ChromotingScriptableObject::STATUS_CLOSED, + ChromotingScriptableObject::ERROR_NONE); } void ChromotingInstance::DidChangeView(const pp::Rect& position, @@ -302,8 +305,7 @@ ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() { void ChromotingInstance::SubmitLoginInfo(const std::string& username, const std::string& password) { - if (host_connection_->state() != - protocol::ConnectionToHost::STATE_CONNECTED) { + if (host_connection_->state() != protocol::ConnectionToHost::CONNECTED) { LOG(INFO) << "Client not connected or already authenticated."; return; } diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc index 28144c4..c19f8ff 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.cc +++ b/remoting/client/plugin/chromoting_scriptable_object.cc @@ -30,8 +30,8 @@ const char kDesktopWidth[] = "desktopWidth"; const char kDesktopSizeUpdate[] = "desktopSizeUpdate"; const char kLoginChallenge[] = "loginChallenge"; const char kSendIq[] = "sendIq"; -const char kQualityAttribute[] = "quality"; const char kStatusAttribute[] = "status"; +const char kErrorAttribute[] = "error"; const char kVideoBandwidthAttribute[] = "videoBandwidth"; const char kVideoCaptureLatencyAttribute[] = "videoCaptureLatency"; const char kVideoEncodeLatencyAttribute[] = "videoEncodeLatency"; @@ -74,13 +74,15 @@ void ChromotingScriptableObject::Init() { AddAttribute("STATUS_CLOSED", Var(STATUS_CLOSED)); AddAttribute("STATUS_FAILED", Var(STATUS_FAILED)); - // Connection quality. - AddAttribute(kQualityAttribute, Var(QUALITY_UNKNOWN)); + // Connection error. + AddAttribute(kErrorAttribute, Var(ERROR_NONE)); - // Connection quality values. - AddAttribute("QUALITY_UNKNOWN", Var(QUALITY_UNKNOWN)); - AddAttribute("QUALITY_GOOD", Var(QUALITY_GOOD)); - AddAttribute("QUALITY_BAD", Var(QUALITY_BAD)); + // Connection status values. + AddAttribute("ERROR_NONE", Var(ERROR_NONE)); + AddAttribute("ERROR_HOST_IS_OFFLINE", Var(ERROR_HOST_IS_OFFLINE)); + AddAttribute("ERROR_SESSION_REJECTED", Var(ERROR_SESSION_REJECTED)); + AddAttribute("ERROR_INCOMPATIBLE_PROTOCOL", Var(ERROR_INCOMPATIBLE_PROTOCOL)); + AddAttribute("ERROR_FAILURE_NONE", Var(ERROR_NETWORK_FAILURE)); // Debug info to display. AddAttribute(kConnectionInfoUpdate, Var()); @@ -226,22 +228,26 @@ Var ChromotingScriptableObject::Call(const Var& method_name, return (this->*(properties_[iter->second].method))(args, exception); } -void ChromotingScriptableObject::SetConnectionInfo(ConnectionStatus status, - ConnectionQuality quality) { - int status_index = property_names_[kStatusAttribute]; - int quality_index = property_names_[kQualityAttribute]; - +void ChromotingScriptableObject::SetConnectionStatus( + ConnectionStatus status, ConnectionError error) { VLOG(1) << "Connection status is updated: " << status; - if (properties_[status_index].attribute.AsInt() != status || - properties_[quality_index].attribute.AsInt() != quality) { - // Update the connection state properties.. + bool signal = false; + + int status_index = property_names_[kStatusAttribute]; + if (properties_[status_index].attribute.AsInt() != status) { properties_[status_index].attribute = Var(status); - properties_[quality_index].attribute = Var(quality); + signal = true; + } - // Signal the Chromoting Tab UI to get the update connection state values. - SignalConnectionInfoChange(); + int error_index = property_names_[kErrorAttribute]; + if (properties_[error_index].attribute.AsInt() != error) { + properties_[error_index].attribute = Var(error); + signal = true; } + + if (signal) + SignalConnectionInfoChange(); } void ChromotingScriptableObject::LogDebugInfo(const std::string& info) { diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h index 04ef206..b138f9f 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.h +++ b/remoting/client/plugin/chromoting_scriptable_object.h @@ -21,20 +21,19 @@ // readonly attribute unsigned short status; // // // Constants for connection status. -// const unsigned short STATUS_UNKNOWN = 0; -// const unsigned short STATUS_CONNECTING = 1; -// const unsigned short STATUS_INITIALIZING = 2; -// const unsigned short STATUS_CONNECTED = 3; -// const unsigned short STATUS_CLOSED = 4; -// const unsigned short STATUS_FAILED = 5; +// const unsigned short STATUS_UNKNOWN; +// const unsigned short STATUS_CONNECTING; +// const unsigned short STATUS_INITIALIZING; +// const unsigned short STATUS_CONNECTED; +// const unsigned short STATUS_CLOSED; +// const unsigned short STATUS_FAILED; // -// // Connection quality. -// readonly attribute unsigned short quality; -// -// // Constants for connection quality -// const unsigned short QUALITY_UNKNOWN = 0; -// const unsigned short QUALITY_GOOD = 1; -// const unsigned short QUALITY_BAD = 2; +// // Constants for connection errors. +// const unsigned short ERROR_NONE; +// const unsigned short ERROR_HOST_IS_OFFLINE; +// const unsigned short ERROR_SESSION_REJECTED; +// const unsigned short ERROR_INCOMPATIBLE_PROTOCOL; +// const unsigned short ERROR_NETWORK_FAILURE; // // // JS callback function so we can signal the JS UI when the connection // // status has been updated. @@ -129,25 +128,27 @@ namespace remoting { class ChromotingInstance; class PepperXmppProxy; -enum ConnectionStatus { - STATUS_UNKNOWN = 0, - STATUS_CONNECTING, - STATUS_INITIALIZING, - STATUS_CONNECTED, - STATUS_CLOSED, - STATUS_FAILED, -}; - -enum ConnectionQuality { - QUALITY_UNKNOWN = 0, - QUALITY_GOOD, - QUALITY_BAD, -}; - class ChromotingScriptableObject : public pp::deprecated::ScriptableObject, public base::SupportsWeakPtr<ChromotingScriptableObject> { public: + enum ConnectionStatus { + STATUS_UNKNOWN = 0, + STATUS_CONNECTING, + STATUS_INITIALIZING, + STATUS_CONNECTED, + STATUS_CLOSED, + STATUS_FAILED, + }; + + enum ConnectionError { + ERROR_NONE = 0, + ERROR_HOST_IS_OFFLINE, + ERROR_SESSION_REJECTED, + ERROR_INCOMPATIBLE_PROTOCOL, + ERROR_NETWORK_FAILURE, + }; + ChromotingScriptableObject( ChromotingInstance* instance, base::MessageLoopProxy* plugin_message_loop); @@ -168,7 +169,7 @@ class ChromotingScriptableObject const std::vector<pp::Var>& args, pp::Var* exception); - void SetConnectionInfo(ConnectionStatus status, ConnectionQuality quality); + void SetConnectionStatus(ConnectionStatus status, ConnectionError error); void LogDebugInfo(const std::string& info); void SetDesktopSize(int width, int height); diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc index 6a58c78..c893d0b 100644 --- a/remoting/client/plugin/pepper_view.cc +++ b/remoting/client/plugin/pepper_view.cc @@ -19,6 +19,28 @@ namespace remoting { +namespace { + +ChromotingScriptableObject::ConnectionError ConvertConnectionError( + protocol::ConnectionToHost::Error error) { + switch (error) { + case protocol::ConnectionToHost::OK: + return ChromotingScriptableObject::ERROR_NONE; + case protocol::ConnectionToHost::HOST_IS_OFFLINE: + return ChromotingScriptableObject::ERROR_HOST_IS_OFFLINE; + case protocol::ConnectionToHost::SESSION_REJECTED: + return ChromotingScriptableObject::ERROR_SESSION_REJECTED; + case protocol::ConnectionToHost::INCOMPATIBLE_PROTOCOL: + return ChromotingScriptableObject::ERROR_INCOMPATIBLE_PROTOCOL; + case protocol::ConnectionToHost::NETWORK_FAILURE: + return ChromotingScriptableObject::ERROR_NETWORK_FAILURE; + } + DLOG(FATAL) << "Unknown error code" << error; + return ChromotingScriptableObject::ERROR_NONE; +} + +} // namespace + PepperView::PepperView(ChromotingInstance* instance, ClientContext* context) : instance_(instance), context_(context), @@ -200,30 +222,40 @@ void PepperView::UnsetSolidFill() { is_static_fill_ = false; } -void PepperView::SetConnectionState(ConnectionState state) { +void PepperView::SetConnectionState(protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) { DCHECK(context_->main_message_loop()->BelongsToCurrentThread()); // TODO(hclam): Re-consider the way we communicate with Javascript. ChromotingScriptableObject* scriptable_obj = instance_->GetScriptableObject(); switch (state) { - case CREATED: + case protocol::ConnectionToHost::CONNECTING: SetSolidFill(kCreatedColor); - scriptable_obj->SetConnectionInfo(STATUS_CONNECTING, QUALITY_UNKNOWN); + scriptable_obj->SetConnectionStatus( + ChromotingScriptableObject::STATUS_CONNECTING, + ConvertConnectionError(error)); break; - case CONNECTED: - UnsetSolidFill(); + case protocol::ConnectionToHost::CONNECTED: scriptable_obj->SignalLoginChallenge(); break; - case DISCONNECTED: + case protocol::ConnectionToHost::AUTHENTICATED: + UnsetSolidFill(); + break; + + case protocol::ConnectionToHost::CLOSED: SetSolidFill(kDisconnectedColor); - scriptable_obj->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN); + scriptable_obj->SetConnectionStatus( + ChromotingScriptableObject::STATUS_CLOSED, + ConvertConnectionError(error)); break; - case FAILED: + case protocol::ConnectionToHost::FAILED: SetSolidFill(kFailedColor); - scriptable_obj->SetConnectionInfo(STATUS_FAILED, QUALITY_UNKNOWN); + scriptable_obj->SetConnectionStatus( + ChromotingScriptableObject::STATUS_FAILED, + ConvertConnectionError(error)); break; } } @@ -233,10 +265,13 @@ void PepperView::UpdateLoginStatus(bool success, const std::string& info) { // TODO(hclam): Re-consider the way we communicate with Javascript. ChromotingScriptableObject* scriptable_obj = instance_->GetScriptableObject(); - if (success) - scriptable_obj->SetConnectionInfo(STATUS_CONNECTED, QUALITY_UNKNOWN); - else + if (success) { + scriptable_obj->SetConnectionStatus( + ChromotingScriptableObject::STATUS_CONNECTED, + ChromotingScriptableObject::ERROR_NONE); + } else { scriptable_obj->SignalLoginChallenge(); + } } bool PepperView::SetPluginSize(const SkISize& plugin_size) { diff --git a/remoting/client/plugin/pepper_view.h b/remoting/client/plugin/pepper_view.h index 1d52cff..0af344d 100644 --- a/remoting/client/plugin/pepper_view.h +++ b/remoting/client/plugin/pepper_view.h @@ -39,9 +39,11 @@ class PepperView : public ChromotingView, virtual void Paint() OVERRIDE; virtual void SetSolidFill(uint32 color) OVERRIDE; virtual void UnsetSolidFill() OVERRIDE; - virtual void SetConnectionState(ConnectionState state) OVERRIDE; - virtual void UpdateLoginStatus(bool success, const std::string& info) - OVERRIDE; + virtual void SetConnectionState( + protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) OVERRIDE; + virtual void UpdateLoginStatus(bool success, + const std::string& info) OVERRIDE; virtual double GetHorizontalScaleRatio() const OVERRIDE; virtual double GetVerticalScaleRatio() const OVERRIDE; diff --git a/remoting/client/plugin/pepper_view_proxy.cc b/remoting/client/plugin/pepper_view_proxy.cc index be37706..119f154 100644 --- a/remoting/client/plugin/pepper_view_proxy.cc +++ b/remoting/client/plugin/pepper_view_proxy.cc @@ -71,15 +71,17 @@ void PepperViewProxy::UnsetSolidFill() { view_->UnsetSolidFill(); } -void PepperViewProxy::SetConnectionState(ConnectionState state) { +void PepperViewProxy::SetConnectionState( + protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) { if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) { plugin_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &PepperViewProxy::SetConnectionState, state)); + this, &PepperViewProxy::SetConnectionState, state, error)); return; } if (view_) - view_->SetConnectionState(state); + view_->SetConnectionState(state, error); } void PepperViewProxy::UpdateLoginStatus(bool success, const std::string& info) { diff --git a/remoting/client/plugin/pepper_view_proxy.h b/remoting/client/plugin/pepper_view_proxy.h index e6b7d0a..8a4914e 100644 --- a/remoting/client/plugin/pepper_view_proxy.h +++ b/remoting/client/plugin/pepper_view_proxy.h @@ -42,7 +42,9 @@ class PepperViewProxy : public base::RefCountedThreadSafe<PepperViewProxy>, virtual void Paint() OVERRIDE; virtual void SetSolidFill(uint32 color) OVERRIDE; virtual void UnsetSolidFill() OVERRIDE; - virtual void SetConnectionState(ConnectionState state) OVERRIDE; + virtual void SetConnectionState( + protocol::ConnectionToHost::State state, + protocol::ConnectionToHost::Error error) OVERRIDE; virtual void UpdateLoginStatus(bool success, const std::string& info) OVERRIDE; diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index 742f4f5..e2fe74a 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -35,7 +35,8 @@ ConnectionToHost::ConnectionToHost( event_callback_(NULL), client_stub_(NULL), video_stub_(NULL), - state_(STATE_EMPTY), + state_(CONNECTING), + error_(OK), control_connected_(false), input_connected_(false), video_connected_(false) { @@ -120,7 +121,7 @@ void ConnectionToHost::OnStateChange( InitSession(); } else if (state == SignalStrategy::StatusObserver::CLOSED) { VLOG(1) << "Connection closed."; - event_callback_->OnConnectionClosed(this); + CloseOnError(NETWORK_FAILURE); } } @@ -153,6 +154,20 @@ void ConnectionToHost::OnIncomingSession( *response = SessionManager::DECLINE; } +void ConnectionToHost::OnClientAuthenticated() { + // TODO(hclam): Don't send anything except authentication request if it is + // not authenticated. + SetState(AUTHENTICATED, OK); + + // Create and enable the input stub now that we're authenticated. + input_sender_.reset( + new InputSender(message_loop_, session_->event_channel())); +} + +ConnectionToHost::State ConnectionToHost::state() const { + return state_; +} + void ConnectionToHost::OnSessionStateChange( Session::State state) { DCHECK(message_loop_->BelongsToCurrentThread()); @@ -160,13 +175,28 @@ void ConnectionToHost::OnSessionStateChange( switch (state) { case Session::FAILED: - CloseOnError(); + switch (session_->error()) { + case Session::PEER_IS_OFFLINE: + CloseOnError(HOST_IS_OFFLINE); + break; + case Session::SESSION_REJECTED: + CloseOnError(SESSION_REJECTED); + break; + case Session::INCOMPATIBLE_PROTOCOL: + CloseOnError(INCOMPATIBLE_PROTOCOL); + break; + case Session::CHANNEL_CONNECTION_ERROR: + CloseOnError(NETWORK_FAILURE); + break; + case Session::OK: + DLOG(FATAL) << "Error code isn't set"; + CloseOnError(NETWORK_FAILURE); + } break; case Session::CLOSED: - state_ = STATE_CLOSED; CloseChannels(); - event_callback_->OnConnectionClosed(this); + SetState(CLOSED, OK); break; case Session::CONNECTED: @@ -179,7 +209,6 @@ void ConnectionToHost::OnSessionStateChange( break; case Session::CONNECTED_CHANNELS: - state_ = STATE_CONNECTED; host_control_sender_.reset( new HostControlSender(message_loop_, session_->control_channel())); dispatcher_.reset(new ClientMessageDispatcher()); @@ -199,7 +228,7 @@ void ConnectionToHost::OnSessionStateChange( void ConnectionToHost::OnVideoChannelInitialized(bool successful) { if (!successful) { LOG(ERROR) << "Failed to connect video channel"; - CloseOnError(); + CloseOnError(NETWORK_FAILURE); return; } @@ -208,14 +237,15 @@ void ConnectionToHost::OnVideoChannelInitialized(bool successful) { } void ConnectionToHost::NotifyIfChannelsReady() { - if (control_connected_ && input_connected_ && video_connected_) - event_callback_->OnConnectionOpened(this); + if (control_connected_ && input_connected_ && video_connected_ && + state_ == CONNECTING) { + SetState(CONNECTED, OK); + } } -void ConnectionToHost::CloseOnError() { - state_ = STATE_FAILED; +void ConnectionToHost::CloseOnError(Error error) { CloseChannels(); - event_callback_->OnConnectionFailed(this); + SetState(FAILED, error); } void ConnectionToHost::CloseChannels() { @@ -228,18 +258,16 @@ void ConnectionToHost::CloseChannels() { video_reader_.reset(); } -void ConnectionToHost::OnClientAuthenticated() { - // TODO(hclam): Don't send anything except authentication request if it is - // not authenticated. - state_ = STATE_AUTHENTICATED; - - // Create and enable the input stub now that we're authenticated. - input_sender_.reset( - new InputSender(message_loop_, session_->event_channel())); -} +void ConnectionToHost::SetState(State state, Error error) { + DCHECK(message_loop_->BelongsToCurrentThread()); + // |error| should be specified only when |state| is set to FAILED. + DCHECK(state == FAILED || error == OK); -ConnectionToHost::State ConnectionToHost::state() const { - return state_; + if (state != state_) { + state_ = state; + error_ = error; + event_callback_->OnConnectionState(state_, error_); + } } } // namespace protocol diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h index c8c1b44..fbf03e2 100644 --- a/remoting/protocol/connection_to_host.h +++ b/remoting/protocol/connection_to_host.h @@ -48,25 +48,27 @@ class ConnectionToHost : public SignalStrategy::StatusObserver, public SessionManager::Listener { public: enum State { - STATE_EMPTY, - STATE_CONNECTED, - STATE_AUTHENTICATED, - STATE_FAILED, - STATE_CLOSED, + CONNECTING, + CONNECTED, + AUTHENTICATED, + FAILED, + CLOSED, + }; + + enum Error { + OK, + HOST_IS_OFFLINE, + SESSION_REJECTED, + INCOMPATIBLE_PROTOCOL, + NETWORK_FAILURE, }; class HostEventCallback { public: virtual ~HostEventCallback() {} - // Called when the network connection is opened. - virtual void OnConnectionOpened(ConnectionToHost* conn) = 0; - - // Called when the network connection is closed. - virtual void OnConnectionClosed(ConnectionToHost* conn) = 0; - - // Called when the network connection has failed. - virtual void OnConnectionFailed(ConnectionToHost* conn) = 0; + // Called when state of the connection changes. + virtual void OnConnectionState(State state, Error error) = 0; }; ConnectionToHost(base::MessageLoopProxy* message_loop, @@ -124,11 +126,13 @@ class ConnectionToHost : public SignalStrategy::StatusObserver, // Callback for |video_reader_|. void OnVideoPacket(VideoPacket* packet); - void CloseOnError(); + void CloseOnError(Error error); // Stops writing in the channels. void CloseChannels(); + void SetState(State state, Error error); + scoped_refptr<base::MessageLoopProxy> message_loop_; pp::Instance* pp_instance_; bool allow_nat_traversal_; @@ -158,6 +162,7 @@ class ConnectionToHost : public SignalStrategy::StatusObserver, // Internal state of the connection. State state_; + Error error_; // State of the channels. bool control_connected_; diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h index 0697b16..aaecbf9 100644 --- a/remoting/protocol/session.h +++ b/remoting/protocol/session.h @@ -49,6 +49,7 @@ class Session : public base::NonThreadSafe { FAILED, }; + // TODO(sergeyu): Move error codes to a separate file. enum Error { OK = 0, PEER_IS_OFFLINE, @@ -58,6 +59,9 @@ class Session : public base::NonThreadSafe { }; typedef Callback1<State>::Type StateChangeCallback; + + // TODO(sergeyu): Specify connection error code when channel + // connection fails. typedef base::Callback<void(net::StreamSocket*)> StreamChannelCallback; typedef base::Callback<void(net::Socket*)> DatagramChannelCallback; |