Chromium Code Reviews| Index: remoting/host/gnubby_auth_handler.cc |
| diff --git a/remoting/host/gnubby_auth_handler.cc b/remoting/host/gnubby_auth_handler.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..35fe09e5ef1fdd9669ab38ff669fc3c7f45ae49a |
| --- /dev/null |
| +++ b/remoting/host/gnubby_auth_handler.cc |
| @@ -0,0 +1,203 @@ |
| +// Copyright 2014 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 "remoting/host/gnubby_auth_handler.h" |
| + |
| +#include "base/file_util.h" |
| +#include "base/json/json_reader.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/values.h" |
| +#include "net/socket/unix_domain_socket_posix.h" |
| +#include "remoting/base/logging.h" |
| +#include "remoting/host/gnubby_utils.h" |
| +#include "remoting/proto/control.pb.h" |
| +#include "remoting/protocol/client_stub.h" |
| + |
| +namespace remoting { |
| + |
| +namespace { |
| + |
| +// The name of the socket to listen for gnubby requests on. |
| +base::LazyInstance<base::FilePath>::Leaky g_gnubby_socket_name = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| +// STL predicate to match by a StreamListenSocket pointer. |
| +class CompareSocket { |
| + public: |
| + explicit CompareSocket(net::StreamListenSocket* socket) : socket_(socket) {} |
| + |
| + bool operator()(const std::pair<net::StreamListenSocket*, int> element) |
| + const { |
| + return socket_ == element.first; |
| + } |
| + |
| + private: |
| + net::StreamListenSocket* socket_; |
| +}; |
| + |
| +// STL predicate to match by a connection id. |
| +class CompareConnection { |
| + public: |
| + explicit CompareConnection(int connection_id) |
| + : connection_id_(connection_id) {} |
| + |
| + bool operator()(const std::pair<net::StreamListenSocket*, int> element) |
| + const { |
| + return connection_id_ == element.second; |
| + } |
| + |
| + private: |
| + int connection_id_; |
| +}; |
| + |
| +} // namespace |
| + |
| +GnubbyAuthHandler::GnubbyAuthHandler(protocol::ClientStub* client_stub) |
| + : client_stub_(client_stub), current_connection_id_(0) { |
| + DCHECK(client_stub_); |
| +} |
| + |
| +GnubbyAuthHandler::~GnubbyAuthHandler() { |
| + for (ActiveSockets::iterator iter = active_sockets_.begin(); |
|
Sergey Ulanov
2014/02/09 22:29:54
STLDeleteContainerPairFirstPointers() from stl_uti
psj
2014/02/10 22:57:22
Done.
|
| + iter != active_sockets_.end(); |
| + ++iter) { |
| + delete iter->first; |
| + } |
| +} |
| + |
| +void GnubbyAuthHandler::DidAccept(net::StreamListenSocket* server, |
| + scoped_ptr<net::StreamListenSocket> socket) { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + active_sockets_.push_back( |
| + std::make_pair(socket.release(), ++current_connection_id_)); |
| +} |
| + |
| +void GnubbyAuthHandler::DidRead(net::StreamListenSocket* socket, |
| + const char* data, |
| + int len) { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + ActiveSockets::iterator iter = std::find_if( |
| + active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket)); |
| + if (iter != active_sockets_.end()) { |
| + std::string json; |
| + if (GnubbyUtils::GetJsonFromRequest(data, len, &json)) { |
| + HOST_LOG << "Received gnubby request"; |
| + DeliverHostDataMessage(iter->second, json); |
| + } else { |
| + HOST_LOG << "Could not decode blob"; |
| + } |
| + } |
| +} |
| + |
| +void GnubbyAuthHandler::DidClose(net::StreamListenSocket* socket) { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + ActiveSockets::iterator iter = std::find_if( |
| + active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket)); |
| + if (iter != active_sockets_.end()) { |
| + delete iter->first; |
| + active_sockets_.erase(iter); |
| + } |
| +} |
| + |
| +void GnubbyAuthHandler::DeliverClientMessage(const std::string message) { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + scoped_ptr<base::Value> value(base::JSONReader::Read(message)); |
| + base::ListValue* list = NULL; |
| + bool result = value->GetAsList(&list); |
| + |
| + std::string auth_message_type; |
| + result = result && list->GetString(0, &auth_message_type); |
| + if (result && auth_message_type == "control") { |
| + std::string payload; |
| + result = list->GetString(1, &payload); |
| + if (result && payload == "auth-v1") { |
| + CreateAuthorizationSocket(); |
| + } |
| + } else if (result && auth_message_type == "data") { |
| + std::string connection_id_str; |
| + std::string payload; |
| + result = list->GetString(1, &connection_id_str); |
| + result = result && list->GetString(2, &payload); |
| + if (result) { |
| + int connection_id = 0; |
| + base::StringToInt(connection_id_str, &connection_id); |
| + |
| + ActiveSockets::iterator iter = |
| + std::find_if(active_sockets_.begin(), |
| + active_sockets_.end(), |
| + CompareConnection(connection_id)); |
| + if (iter != active_sockets_.end()) { |
| + HOST_LOG << "Sending gnubby response"; |
| + |
| + std::string reply; |
| + GnubbyUtils::GetResponseFromJson(payload, &reply); |
| + |
| + iter->first->Send(reply); |
| + } |
| + } |
| + } |
| +} |
| + |
| +void GnubbyAuthHandler::DeliverHostControlMessage( |
| + const std::string control_type, |
| + const std::string data) const { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + protocol::ExtensionMessage message; |
| + message.set_type("gnubby-auth"); |
| + message.set_data("control " + control_type + " " + data); |
|
Sergey Ulanov
2014/02/09 22:29:54
It seems strange to use JSON to encode message typ
psj
2014/02/10 22:57:22
They aren't so different as they are both a space-
Sergey Ulanov
2014/02/11 08:20:37
I was pointing at DeliverClientMessage() - that me
psj
2014/02/12 09:01:01
Ah, I see what you mean now. This is due to the ex
|
| + |
| + client_stub_->DeliverHostMessage(message); |
| +} |
| + |
| +void GnubbyAuthHandler::DeliverHostDataMessage(int connection_id, |
| + const std::string data) const { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + protocol::ExtensionMessage message; |
| + message.set_type("gnubby-auth"); |
| + message.set_data("data " + base::IntToString(connection_id) + " " + data); |
| + |
| + client_stub_->DeliverHostMessage(message); |
| +} |
| + |
| +void GnubbyAuthHandler::SetGnubbySocketName(base::FilePath gnubby_socket_name) { |
| + g_gnubby_socket_name.Get() = gnubby_socket_name; |
| +} |
| + |
| +bool GnubbyAuthHandler::HasActiveSocketForTesting( |
| + net::StreamListenSocket* socket) const { |
| + return std::find_if(active_sockets_.begin(), |
| + active_sockets_.end(), |
| + CompareSocket(socket)) != active_sockets_.end(); |
| +} |
| + |
| +void GnubbyAuthHandler::CreateAuthorizationSocket() { |
| + DCHECK(CalledOnValidThread()); |
| + |
| + if (!g_gnubby_socket_name.Get().empty()) { |
| + // If the file already exists, a socket in use error is returned. |
| + base::DeleteFile(g_gnubby_socket_name.Get(), false); |
| + |
| + HOST_LOG << "Listening for gnubby requests on " |
| + << g_gnubby_socket_name.Get().value(); |
| + |
| + auth_socket_ = net::UnixDomainSocket::CreateAndListen( |
| + g_gnubby_socket_name.Get().value(), |
| + this, |
| + net::UnixDomainSocket::NoAuthentication()); |
| + if (!auth_socket_.get()) { |
| + HOST_LOG << "Failed to open socket for gnubby requests"; |
| + } |
| + } else { |
| + HOST_LOG << "No gnubby socket name specified"; |
| + } |
| +} |
| + |
| +} // namespace remoting |