OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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/gnubby_auth_handler.h" |
| 6 |
| 7 #include "base/base64.h" |
| 8 #include "base/json/json_reader.h" |
| 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/values.h" |
| 11 #include "net/base/net_errors.h" |
| 12 #include "net/socket/client_socket_factory.h" |
| 13 #include "remoting/base/logging.h" |
| 14 #include "remoting/host/gnubby_advertiser.h" |
| 15 #include "remoting/host/gnubby_connection.h" |
| 16 #include "remoting/host/gnubby_connection_factory.h" |
| 17 #include "remoting/proto/control.pb.h" |
| 18 #include "remoting/protocol/client_stub.h" |
| 19 |
| 20 namespace remoting { |
| 21 |
| 22 GnubbyAuthHandler::GnubbyAuthHandler( |
| 23 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, |
| 24 GnubbyConnectionFactory* gnubby_connection_factory, |
| 25 protocol::ClientStub* client_stub) |
| 26 : network_task_runner_(network_task_runner), |
| 27 gnubby_connection_factory_(gnubby_connection_factory), |
| 28 client_stub_(client_stub), |
| 29 current_connection_id_(0), |
| 30 gnubbyd_listener_port_(0) { |
| 31 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 32 DCHECK(gnubby_connection_factory_); |
| 33 DCHECK(client_stub_); |
| 34 } |
| 35 |
| 36 GnubbyAuthHandler::~GnubbyAuthHandler() { |
| 37 for (ConnectionMap::iterator iter = active_connections_.begin(); |
| 38 iter != active_connections_.end(); |
| 39 ++iter) { |
| 40 delete iter->second; |
| 41 } |
| 42 } |
| 43 |
| 44 void GnubbyAuthHandler::DeliverClientMessage(const std::string message) { |
| 45 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 46 |
| 47 scoped_ptr<base::Value> value; |
| 48 value.reset(base::JSONReader::Read(message)); |
| 49 DCHECK(value->IsType(base::Value::TYPE_LIST)); |
| 50 |
| 51 base::ListValue* list = NULL; |
| 52 DCHECK(value->GetAsList(&list)); |
| 53 |
| 54 std::string auth_message_type; |
| 55 DCHECK(list->GetString(0, &auth_message_type)); |
| 56 |
| 57 if (auth_message_type == "control") { |
| 58 std::string payload; |
| 59 DCHECK(list->GetString(1, &payload)); |
| 60 |
| 61 if (payload == "auth-v1") { |
| 62 CreateGnubbydSocket(); |
| 63 AcceptGnubbydConnections(); |
| 64 |
| 65 scoped_refptr<GnubbyAdvertiser> advertiser = new GnubbyAdvertiser( |
| 66 network_task_runner_, net::ClientSocketFactory::GetDefaultFactory()); |
| 67 advertiser->Advertise(gnubbyd_listener_port_); |
| 68 } |
| 69 } else if (auth_message_type == "data") { |
| 70 std::string connection_id_str; |
| 71 DCHECK(list->GetString(1, &connection_id_str)); |
| 72 |
| 73 std::string payload; |
| 74 DCHECK(list->GetString(2, &payload)); |
| 75 |
| 76 std::string decoded_payload; |
| 77 base::Base64Decode(payload, &decoded_payload); |
| 78 |
| 79 int connection_id = 0; |
| 80 base::StringToInt(connection_id_str, &connection_id); |
| 81 |
| 82 ConnectionMap::iterator iter = active_connections_.find(connection_id); |
| 83 if (iter != active_connections_.end()) { |
| 84 iter->second->Write(decoded_payload); |
| 85 } |
| 86 } |
| 87 } |
| 88 |
| 89 void GnubbyAuthHandler::ConnectionClosed(int connection_id) { |
| 90 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 91 |
| 92 DeliverHostControlMessage("close", base::IntToString(connection_id)); |
| 93 |
| 94 ConnectionMap::iterator iter = active_connections_.find(connection_id); |
| 95 if (iter != active_connections_.end()) { |
| 96 delete iter->second; |
| 97 active_connections_.erase(iter); |
| 98 } |
| 99 } |
| 100 |
| 101 void GnubbyAuthHandler::ConnectionError(int connection_id, int result) { |
| 102 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 103 |
| 104 HOST_LOG << "Error on connection " << connection_id << ": " << result; |
| 105 ConnectionClosed(connection_id); |
| 106 } |
| 107 |
| 108 void GnubbyAuthHandler::DeliverHostControlMessage( |
| 109 const std::string control_type, |
| 110 const std::string data) const { |
| 111 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 112 |
| 113 protocol::ExtensionMessage message; |
| 114 message.set_type("gnubby-auth"); |
| 115 message.set_data("control " + control_type + " " + data); |
| 116 |
| 117 client_stub_->DeliverHostMessage(message); |
| 118 } |
| 119 |
| 120 void GnubbyAuthHandler::DeliverHostDataMessage(int connection_id, |
| 121 const std::string data) const { |
| 122 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 123 |
| 124 std::string encoded_data; |
| 125 base::Base64Encode(data, &encoded_data); |
| 126 |
| 127 protocol::ExtensionMessage message; |
| 128 message.set_type("gnubby-auth"); |
| 129 message.set_data("data " + base::IntToString(connection_id) + " " + |
| 130 encoded_data); |
| 131 |
| 132 client_stub_->DeliverHostMessage(message); |
| 133 } |
| 134 |
| 135 void GnubbyAuthHandler::SetGnubbydSocketForTesting( |
| 136 net::TCPServerSocket* gnubbyd_socket) { |
| 137 gnubbyd_socket_.reset(gnubbyd_socket); |
| 138 AcceptGnubbydConnections(); |
| 139 } |
| 140 |
| 141 int GnubbyAuthHandler::AddGnubbyConnectionForTesting( |
| 142 net::StreamSocket* pending_socket) { |
| 143 pending_socket_.reset(pending_socket); |
| 144 OnAccept(net::ERR_IO_PENDING); |
| 145 return current_connection_id_; |
| 146 } |
| 147 |
| 148 bool GnubbyAuthHandler::HasGnubbyConnectionForTesting(int connection_id) const { |
| 149 return active_connections_.find(connection_id) != active_connections_.end(); |
| 150 } |
| 151 |
| 152 void GnubbyAuthHandler::CreateGnubbydSocket() { |
| 153 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 154 |
| 155 net::NetLog::Source source; |
| 156 gnubbyd_socket_.reset(new net::TCPServerSocket(NULL, source)); |
| 157 |
| 158 net::IPAddressNumber local_ip; |
| 159 net::ParseIPLiteralToNumber("127.0.0.1", &local_ip); |
| 160 |
| 161 net::IPEndPoint local_endpoint(local_ip, 0); |
| 162 int result = gnubbyd_socket_->Listen(local_endpoint, 1); |
| 163 if (result != net::OK) { |
| 164 HOST_LOG << "Failed to listen: " << result; |
| 165 return; |
| 166 } |
| 167 |
| 168 net::IPEndPoint listener_endpoint; |
| 169 result = gnubbyd_socket_->GetLocalAddress(&listener_endpoint); |
| 170 if (result != net::OK) { |
| 171 HOST_LOG << "Failed to get local endpoint: " << result; |
| 172 return; |
| 173 } |
| 174 |
| 175 HOST_LOG << "Listening on endpoint: " << listener_endpoint.ToString(); |
| 176 |
| 177 gnubbyd_listener_port_ = listener_endpoint.port(); |
| 178 } |
| 179 |
| 180 void GnubbyAuthHandler::AcceptGnubbydConnections() { |
| 181 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 182 |
| 183 int result = gnubbyd_socket_->Accept( |
| 184 &pending_socket_, |
| 185 base::Bind(&GnubbyAuthHandler::OnAccept, base::Unretained(this))); |
| 186 if (result != net::ERR_IO_PENDING) { |
| 187 OnAccept(result); |
| 188 } |
| 189 } |
| 190 |
| 191 void GnubbyAuthHandler::OnAccept(int result) { |
| 192 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 193 |
| 194 if (result == net::OK) { |
| 195 int connection_id = ++current_connection_id_; |
| 196 active_connections_[connection_id] = gnubby_connection_factory_->Create( |
| 197 network_task_runner_, this, connection_id, pending_socket_.release()); |
| 198 active_connections_[connection_id]->Read(); |
| 199 AcceptGnubbydConnections(); |
| 200 } |
| 201 } |
| 202 |
| 203 } // namespace remoting |
OLD | NEW |