OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/host/simple_host.h" |
| 6 |
| 7 #include "base/stl_util-inl.h" |
| 8 #include "build/build_config.h" |
| 9 #include "remoting/base/protocol_decoder.h" |
| 10 #include "remoting/host/session_manager.h" |
| 11 #include "remoting/jingle_glue/jingle_channel.h" |
| 12 |
| 13 namespace remoting { |
| 14 |
| 15 SimpleHost::SimpleHost(const std::string& username, |
| 16 const std::string& password, |
| 17 Capturer* capturer, |
| 18 Encoder* encoder, |
| 19 EventExecutor* executor) |
| 20 : capture_thread_("CaptureThread"), |
| 21 encode_thread_("EncodeThread"), |
| 22 username_(username), |
| 23 password_(password), |
| 24 capturer_(capturer), |
| 25 encoder_(encoder), |
| 26 executor_(executor) { |
| 27 } |
| 28 |
| 29 void SimpleHost::Run() { |
| 30 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 31 |
| 32 // Submit a task to perform host registration. We'll also start |
| 33 // listening to connection if registration is done. |
| 34 RegisterHost(); |
| 35 |
| 36 // Run the main message loop. This is the main loop of this host |
| 37 // object. |
| 38 main_loop_.Run(); |
| 39 } |
| 40 |
| 41 // This method is called when we need to the host process. |
| 42 void SimpleHost::DestroySession() { |
| 43 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 44 |
| 45 // First we tell the session to pause and then we wait until all |
| 46 // the tasks are done. |
| 47 session_->Pause(); |
| 48 |
| 49 // TODO(hclam): Revise the order. |
| 50 encode_thread_.Stop(); |
| 51 capture_thread_.Stop(); |
| 52 } |
| 53 |
| 54 // This method talks to the cloud to register the host process. If |
| 55 // successful we will start listening to network requests. |
| 56 void SimpleHost::RegisterHost() { |
| 57 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 58 DCHECK(!jingle_client_); |
| 59 |
| 60 // Connect to the talk network with a JingleClient. |
| 61 jingle_client_ = new JingleClient(); |
| 62 jingle_client_->Init(username_, password_, this); |
| 63 } |
| 64 |
| 65 // This method is called if a client is connected to this object. |
| 66 void SimpleHost::OnClientConnected(ClientConnection* client) { |
| 67 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 68 |
| 69 // Create a new RecordSession if there was none. |
| 70 if (!session_) { |
| 71 // The first we need to make sure capture and encode thread are |
| 72 // running. |
| 73 capture_thread_.Start(); |
| 74 encode_thread_.Start(); |
| 75 |
| 76 // Then we create a SessionManager passing the message loops that |
| 77 // it should run on. |
| 78 // Note that we pass the ownership of the capturer and encoder to |
| 79 // the session manager. |
| 80 DCHECK(capturer_.get()); |
| 81 DCHECK(encoder_.get()); |
| 82 session_ = new SessionManager(capture_thread_.message_loop(), |
| 83 encode_thread_.message_loop(), |
| 84 &main_loop_, |
| 85 capturer_.release(), |
| 86 encoder_.release()); |
| 87 |
| 88 // Immediately add the client and start the session. |
| 89 session_->AddClient(client); |
| 90 session_->Start(); |
| 91 LOG(INFO) << "Session manager started"; |
| 92 } else { |
| 93 // If a session manager already exists we simply add the new client. |
| 94 session_->AddClient(client); |
| 95 } |
| 96 } |
| 97 |
| 98 void SimpleHost::OnClientDisconnected(ClientConnection* client) { |
| 99 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 100 |
| 101 // Remove the client from the session manager. |
| 102 DCHECK(session_); |
| 103 session_->RemoveClient(client); |
| 104 |
| 105 // Also remove reference to ClientConnection from this object. |
| 106 client_ = NULL; |
| 107 |
| 108 // TODO(hclam): If the last client has disconnected we need destroy |
| 109 // the session manager and shutdown the capture and encode threads. |
| 110 // Right now we assume there's only one client. |
| 111 DestroySession(); |
| 112 } |
| 113 |
| 114 //////////////////////////////////////////////////////////////////////////// |
| 115 // ClientConnection::EventHandler implementations |
| 116 void SimpleHost::HandleMessages(ClientConnection* client, |
| 117 ClientMessageList* messages) { |
| 118 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 119 |
| 120 // Delegate the messages to EventExecutor and delete the unhandled |
| 121 // messages. |
| 122 DCHECK(executor_.get()); |
| 123 executor_->HandleInputEvents(messages); |
| 124 STLDeleteElements<ClientMessageList>(messages); |
| 125 } |
| 126 |
| 127 void SimpleHost::OnConnectionOpened(ClientConnection* client) { |
| 128 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 129 |
| 130 // Completes the client connection. |
| 131 LOG(INFO) << "Connection to client established."; |
| 132 OnClientConnected(client_.get()); |
| 133 } |
| 134 |
| 135 void SimpleHost::OnConnectionClosed(ClientConnection* client) { |
| 136 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 137 |
| 138 // Completes the client connection. |
| 139 LOG(INFO) << "Connection to client closed."; |
| 140 OnClientDisconnected(client_.get()); |
| 141 } |
| 142 |
| 143 void SimpleHost::OnConnectionFailed(ClientConnection* client) { |
| 144 DCHECK_EQ(&main_loop_, MessageLoop::current()); |
| 145 |
| 146 // The client has disconnected. |
| 147 LOG(ERROR) << "Connection failed unexpectedly."; |
| 148 OnClientDisconnected(client_.get()); |
| 149 } |
| 150 |
| 151 //////////////////////////////////////////////////////////////////////////// |
| 152 // JingleClient::Callback implementations |
| 153 void SimpleHost::OnStateChange(JingleClient* jingle_client, |
| 154 JingleClient::State state) { |
| 155 DCHECK_EQ(jingle_client_.get(), jingle_client); |
| 156 |
| 157 if (state == JingleClient::CONNECTED) { |
| 158 // TODO(hclam): Change to use LOG(INFO). |
| 159 // LOG(INFO) << "Host connected as " |
| 160 // << jingle_client->GetFullJid() << "." << std::endl; |
| 161 printf("Host connected as %s\n", jingle_client->GetFullJid().c_str()); |
| 162 |
| 163 // Start heartbeating after we connected |
| 164 heartbeat_sender_ = new HeartbeatSender(); |
| 165 // TODO(sergeyu): where do we get host id? |
| 166 heartbeat_sender_->Start(jingle_client_.get(), "HostID"); |
| 167 } else if (state == JingleClient::CLOSED) { |
| 168 LOG(INFO) << "Host disconnected from talk network." << std::endl; |
| 169 |
| 170 heartbeat_sender_ = NULL; |
| 171 } |
| 172 } |
| 173 |
| 174 bool SimpleHost::OnAcceptConnection( |
| 175 JingleClient* jingle_client, const std::string& jid, |
| 176 JingleChannel::Callback** channel_callback) { |
| 177 DCHECK_EQ(jingle_client_.get(), jingle_client); |
| 178 |
| 179 if (client_.get()) |
| 180 return false; |
| 181 |
| 182 LOG(INFO) << "Client connected: " << jid << std::endl; |
| 183 |
| 184 // If we accept the connected then create a client object and set the |
| 185 // callback. |
| 186 client_ = new ClientConnection(&main_loop_, new ProtocolDecoder(), this); |
| 187 *channel_callback = client_.get(); |
| 188 return true; |
| 189 } |
| 190 |
| 191 void SimpleHost::OnNewConnection(JingleClient* jingle_client, |
| 192 scoped_refptr<JingleChannel> channel) { |
| 193 DCHECK_EQ(jingle_client_.get(), jingle_client); |
| 194 |
| 195 // Since the session manager has not started, it is still safe to access |
| 196 // the client directly. Note that we give the ownership of the channel |
| 197 // to the client. |
| 198 client_->set_jingle_channel(channel); |
| 199 } |
| 200 |
| 201 } // namespace remoting |
OLD | NEW |