Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "blimp/client/session/assignment_source.h" | 5 #include "blimp/client/session/assignment_source.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | |
| 8 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_util.h" | |
| 9 #include "base/location.h" | 11 #include "base/location.h" |
| 10 #include "base/numerics/safe_conversions.h" | 12 #include "base/numerics/safe_conversions.h" |
| 11 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 12 #include "blimp/client/app/blimp_client_switches.h" | 14 #include "blimp/client/app/blimp_client_switches.h" |
| 15 #include "net/base/hash_value.h" | |
| 13 #include "net/base/ip_address.h" | 16 #include "net/base/ip_address.h" |
| 14 #include "net/base/ip_endpoint.h" | 17 #include "net/base/ip_endpoint.h" |
| 18 #include "net/cert/pem_tokenizer.h" | |
| 15 | 19 |
| 16 namespace blimp { | 20 namespace blimp { |
| 17 namespace { | 21 namespace { |
| 18 | 22 |
| 19 // TODO(kmarshall): Take values from configuration data. | 23 // TODO(kmarshall): Take values from configuration data. |
| 20 const char kDummyClientToken[] = "MyVoiceIsMyPassport"; | 24 const char kDummyClientToken[] = "MyVoiceIsMyPassport"; |
| 21 const std::string kDefaultBlimpletIPAddress = "127.0.0.1"; | 25 const std::string kDefaultBlimpletIPAddress = "127.0.0.1"; |
| 22 const uint16_t kDefaultBlimpletTCPPort = 25467; | 26 const uint16_t kNoPort = 0; |
|
Wez
2016/02/12 02:31:13
nit: kPortNotSet or kInvalidPort?
Kevin M
2016/02/13 00:44:17
Done.
| |
| 23 | 27 |
| 24 net::IPAddress GetBlimpletIPAddress() { | 28 net::IPAddress GetBlimpletIPAddress() { |
| 25 std::string host; | 29 std::string host; |
| 26 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 30 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 27 switches::kBlimpletHost)) { | 31 switches::kBlimpletHost)) { |
| 28 host = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 32 host = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 29 switches::kBlimpletHost); | 33 switches::kBlimpletHost); |
| 30 } else { | 34 } else { |
| 31 host = kDefaultBlimpletIPAddress; | 35 host = kDefaultBlimpletIPAddress; |
| 32 } | 36 } |
| 33 net::IPAddress ip_address; | 37 net::IPAddress ip_address; |
| 34 if (!ip_address.AssignFromIPLiteral(host)) | 38 if (!ip_address.AssignFromIPLiteral(host)) |
| 35 CHECK(false) << "Invalid BlimpletAssignment host " << host; | 39 CHECK(false) << "Invalid BlimpletAssignment host " << host; |
| 36 return ip_address; | 40 return ip_address; |
| 37 } | 41 } |
| 38 | 42 |
| 39 uint16_t GetBlimpletTCPPort() { | 43 uint16_t GetBlimpletTCPPort() { |
| 40 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 44 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 41 switches::kBlimpletTCPPort)) { | 45 switches::kBlimpletTCPPort)) { |
| 42 std::string port_str = | 46 std::string port_str = |
| 43 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 47 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 44 switches::kBlimpletTCPPort); | 48 switches::kBlimpletTCPPort); |
| 45 uint port_64t; | 49 uint port_64t; |
|
Wez
2016/02/12 02:31:13
nit: This needs to be explicitly initialized.
Kevin M
2016/02/13 00:44:17
Done.
| |
| 46 if (!base::StringToUint(port_str, &port_64t) || | 50 if (!base::StringToUint(port_str, &port_64t) || |
| 47 !base::IsValueInRangeForNumericType<uint16_t>(port_64t)) { | 51 !base::IsValueInRangeForNumericType<uint16_t>(port_64t)) { |
| 48 CHECK(false) << "Invalid BlimpletAssignment port " << port_str; | 52 CHECK(false) << "Invalid BlimpletAssignment port " << port_str; |
| 49 } | 53 } |
| 50 return base::checked_cast<uint16_t>(port_64t); | 54 return base::checked_cast<uint16_t>(port_64t); |
| 51 } else { | 55 } else { |
| 52 return kDefaultBlimpletTCPPort; | 56 return kNoPort; |
| 53 } | 57 } |
| 54 } | 58 } |
| 55 | 59 |
| 60 uint16_t GetBlimpletSSLPort() { | |
|
Wez
2016/02/12 02:31:13
This is basically identical to the TCP port one ab
Kevin M
2016/02/13 00:44:17
Done.
| |
| 61 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 62 switches::kBlimpletSSLPort)) { | |
|
Wez
2016/02/12 02:31:13
GetSwitchValueASCII returns an empty string if the
Kevin M
2016/02/13 00:44:18
Done.
| |
| 63 std::string port_str = | |
| 64 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 65 switches::kBlimpletSSLPort); | |
| 66 uint port_64t; | |
|
Wez
2016/02/12 02:31:13
nit: This needs to be explicitly initialized.
Kevin M
2016/02/13 00:44:17
Done.
| |
| 67 if (!base::StringToUint(port_str, &port_64t) || | |
| 68 !base::IsValueInRangeForNumericType<uint16_t>(port_64t)) { | |
| 69 CHECK(false) << "Invalid SSL port " << port_str; | |
|
Wez
2016/02/12 02:31:13
nit: Save the result of StringToUint || IsValue..
Kevin M
2016/02/13 00:44:17
Done.
| |
| 70 } | |
| 71 return base::checked_cast<uint16_t>(port_64t); | |
| 72 } else { | |
| 73 return kNoPort; | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 base::FilePath GetBlimpletCertPath() { | |
|
Wez
2016/02/12 02:31:13
This function is redundant; GetSwitchValuePath() a
Kevin M
2016/02/13 00:44:18
Done.
| |
| 78 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 79 switches::kBlimpletCertPath)) { | |
| 80 return base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( | |
| 81 switches::kBlimpletCertPath); | |
| 82 } | |
| 83 return base::FilePath(); | |
| 84 } | |
| 85 | |
| 56 } // namespace | 86 } // namespace |
| 57 | 87 |
| 58 namespace client { | 88 namespace client { |
| 59 | 89 |
| 90 Assignment::Assignment() {} | |
|
Wez
2016/02/12 02:31:13
See above re inline init; you need to make sure to
Kevin M
2016/02/13 00:44:17
Done.
| |
| 91 | |
| 92 Assignment::~Assignment() {} | |
| 93 | |
| 60 AssignmentSource::AssignmentSource( | 94 AssignmentSource::AssignmentSource( |
| 61 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) | 95 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) |
| 62 : main_task_runner_(main_task_runner) {} | 96 : main_task_runner_(main_task_runner), io_thread_("CertFileThread") { |
| 97 base::Thread::Options options; | |
| 98 options.message_loop_type = base::MessageLoop::TYPE_IO; | |
| 99 io_thread_.StartWithOptions(options); | |
|
Wez
2016/02/12 02:31:13
Cleaner to avoid creating this thread until you ac
Kevin M
2016/02/13 00:44:17
Done.
| |
| 100 } | |
| 63 | 101 |
| 64 AssignmentSource::~AssignmentSource() {} | 102 AssignmentSource::~AssignmentSource() {} |
| 65 | 103 |
| 104 void AssignmentSource::ReadFromDisk( | |
|
Wez
2016/02/12 02:31:13
As noted elsewhere, this function can be a static
Kevin M
2016/02/13 00:44:17
Done.
| |
| 105 base::FilePath path, | |
| 106 const base::Callback<void(const std::string&)>& callback) { | |
| 107 if (!io_thread_.task_runner()->RunsTasksOnCurrentThread()) { | |
| 108 // Execute file reads on the I/O thread. | |
| 109 io_thread_.task_runner()->PostTask( | |
| 110 FROM_HERE, base::Bind(&AssignmentSource::ReadFromDisk, | |
| 111 base::Unretained(this), path, callback)); | |
| 112 return; | |
|
Wez
2016/02/12 02:31:13
ICK! This sort of trampolining is safe while the
Kevin M
2016/02/13 00:44:18
Done.
| |
| 113 } | |
| 114 | |
| 115 std::string output; | |
| 116 if (!base::ReadFileToString(path, &output)) { | |
| 117 LOG(ERROR) << "Couldn't read cert from file: " << path.LossyDisplayName(); | |
|
Wez
2016/02/12 02:31:13
Why LOG(ERROR) when we CHECK for everything else?
Kevin M
2016/02/13 00:44:18
Done.
| |
| 118 } | |
| 119 | |
| 120 main_task_runner_->PostTask(FROM_HERE, base::Bind(callback, output)); | |
|
Wez
2016/02/12 02:31:13
This doesn't match the API comment.
Kevin M
2016/02/13 00:44:17
Acknowledged.
| |
| 121 } | |
| 122 | |
| 123 void AssignmentSource::ParseCertForAssignment( | |
| 124 Assignment assignment, | |
| 125 const AssignmentCallback& callback, | |
| 126 const std::string& cert_str) { | |
| 127 if (!cert_str.empty()) { | |
|
Wez
2016/02/12 02:31:13
Surely you can't reach here if it's empty, so this
Kevin M
2016/02/13 00:44:17
Done.
| |
| 128 scoped_refptr<net::X509Certificate> cert; | |
|
Wez
2016/02/12 02:31:13
Doesn't look like you use this?
Kevin M
2016/02/13 00:44:17
Done.
| |
| 129 net::PEMTokenizer pem_tokenizer(cert_str, {"CERTIFICATE"}); | |
| 130 int num_certs = 0; | |
|
Wez
2016/02/12 02:31:13
Rather than counting the certs, you can surely jus
Kevin M
2016/02/13 00:44:17
Done.
| |
| 131 for (; pem_tokenizer.GetNext(); ++num_certs) { | |
| 132 assignment.cert = net::X509Certificate::CreateFromBytes( | |
| 133 pem_tokenizer.data().data(), pem_tokenizer.data().length()); | |
| 134 if (!assignment.cert) { | |
| 135 LOG(ERROR) << "Couldn't parse cert!"; | |
| 136 } else { | |
| 137 DVLOG(1) << "Parsed X509 cert."; | |
| 138 } | |
| 139 } | |
| 140 if (num_certs != 1) { | |
| 141 LOG(ERROR) << "Expected exactly 1 CERTIFICATE block, but found " | |
| 142 << num_certs << " blocks instead."; | |
| 143 assignment.cert = nullptr; | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 main_task_runner_->PostTask(FROM_HERE, base::Bind(callback, assignment)); | |
|
Wez
2016/02/12 02:31:13
You're already on the main task runner, with a cle
Kevin M
2016/02/13 00:44:18
This line is from Tommy's initial impl, I was thin
| |
| 148 } | |
| 149 | |
| 66 void AssignmentSource::GetAssignment(const AssignmentCallback& callback) { | 150 void AssignmentSource::GetAssignment(const AssignmentCallback& callback) { |
| 67 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 151 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 68 Assignment assignment; | 152 Assignment assignment; |
| 69 assignment.ip_endpoint = | 153 assignment.ip_addresses.push_back(GetBlimpletIPAddress()); |
| 70 net::IPEndPoint(GetBlimpletIPAddress(), GetBlimpletTCPPort()); | 154 if (GetBlimpletTCPPort() > 0) { |
|
Wez
2016/02/12 02:31:13
This if() is always true, since the Get*Port() met
Kevin M
2016/02/13 00:44:17
Done.
| |
| 155 assignment.tcp_port = GetBlimpletTCPPort(); | |
| 156 } | |
| 157 if (GetBlimpletSSLPort() > 0) { | |
| 158 assignment.ssl_port = GetBlimpletSSLPort(); | |
| 159 } | |
| 71 assignment.client_token = kDummyClientToken; | 160 assignment.client_token = kDummyClientToken; |
| 72 main_task_runner_->PostTask(FROM_HERE, base::Bind(callback, assignment)); | 161 |
| 162 base::FilePath cert_path = GetBlimpletCertPath(); | |
| 163 if (!cert_path.empty()) { | |
| 164 ReadFromDisk(cert_path, | |
| 165 base::Bind(&AssignmentSource::ParseCertForAssignment, | |
| 166 base::Unretained(this), assignment, callback)); | |
|
Wez
2016/02/12 02:31:13
See notes above re combining file-read and cert-pa
Kevin M
2016/02/13 00:44:18
Done.
| |
| 167 } else { | |
| 168 main_task_runner_->PostTask(FROM_HERE, base::Bind(callback, assignment)); | |
|
Wez
2016/02/12 02:31:13
Assert that the SSL port is kNoPort in this case?
Kevin M
2016/02/13 00:44:17
Done.
| |
| 169 } | |
| 73 } | 170 } |
| 74 | 171 |
| 75 } // namespace client | 172 } // namespace client |
| 76 } // namespace blimp | 173 } // namespace blimp |
| OLD | NEW |