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