Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: net/tools/ct_mapper/ct_mapper_main.cc

Issue 1238413004: Framework for iterating over certificates in CT database from Chromium code. (not for review) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make samples page work Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/ct_mapper/README ('k') | net/tools/ct_mapper/dump-ct.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 <iostream>
6
7 #include "base/at_exit.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/files/file_util.h"
11 #include "base/format_macros.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "net/tools/ct_mapper/entry_reader.h"
15 #include "net/tools/ct_mapper/mapper.h"
16 #include "net/tools/ct_mapper/metrics.h"
17 #include "net/tools/ct_mapper/my_visitor.h"
18 #include "net/tools/ct_mapper/write_results.h"
19
20 namespace net {
21 namespace {
22
23 const char kClobberSwitch[] = "clobber";
24 const char kNumThreadsSwitch[] = "threads";
25 const char kNumSamplesPerBucket[] = "samples";
26 const char kChunkSizeSwitch[] = "chunk_size";
27 const char kMaxElapsedSeconds[] = "max_elapsed_seconds";
28 const char kMaxPendingChunksSwitch[] = "max_pending_chunks";
29
30 const char kUsage[] =
31 "Usage: ct_mapper [options] {inpath} {outpath}\n"
32 "\n"
33 "Iterates over all the certificate transparency entries in {inpath}. Each\n"
34 "entry is categorized into zero or more buckets.\n"
35 "\n"
36 " {inpath} Path to a directory containing a dump of the CT datbase\n"
37 " (can be created using dump-ct.sh)\n"
38 "\n"
39 " {outpath} Directory where results will be written. The results\n"
40 " include an HTML file for exploring the data, as well \n"
41 " as samples from each bucket.\n"
42 "\n"
43 "OPTIONS\n"
44 "\n"
45 " --threads={num} Uses {num} threads to process all the data. "
46 "Default=%" PRIuS
47 ".\n"
48 "\n"
49 " --samples={num} Writes up to {num} samples for each bucket. "
50 "Default=%" PRIuS
51 ".\n"
52 "\n"
53 " --chunk_size={num} The smallest size of work that is consumed by a "
54 "worker thread. It is a count of the number of entries. At one "
55 "extreme the chunk size could be set to 1, in which case each worker "
56 "thread can dequeue one entry at a time (which might not be the best "
57 "for memory locality, or amount of locking overhead). Default=%" PRIuS
58 ".\n"
59 "\n"
60 " --max_elapsed_seconds={num} The total amount of time to run before "
61 "aborting.\n"
62 "\n"
63 " --max_pending_chunks={num} The maximum number of unconsumed chunks "
64 "waiting to be grabbed by worker threads. Default=%" PRIuS ".\n";
65
66 // Helper to get a command line switch as an unsigned integer.
67 WARN_UNUSED_RESULT bool GetNumericSwitch(const base::CommandLine& command_line,
68 const std::string& name,
69 size_t* value,
70 size_t default_value) {
71 *value = default_value;
72
73 std::string string_value = command_line.GetSwitchValueASCII(name);
74
75 if (!string_value.empty()) {
76 if (!base::StringToSizeT(string_value, value)) {
77 std::cerr << "ERROR: --" << name << " must be an unsigned integer\n";
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 // Makes sure the input path is a directory, and looks like it contains CT
86 // entries.
87 bool GetInputPath(const base::CommandLine::StringType& value,
88 base::FilePath* path) {
89 *path = base::FilePath(value);
90
91 if (!base::PathExists(*path)) {
92 std::cerr << "ERROR: input path doesn't exist: " << value << " \n";
93 return false;
94 }
95
96 if (!base::DirectoryExists(*path)) {
97 std::cerr << "ERROR: input path is not a directory: " << value << " \n";
98 return false;
99 }
100
101 if (!base::PathExists(path->AppendASCII("entries.bin"))) {
102 std::cerr << "ERROR: input directory does not contain an entries.bin file: "
103 << value << " \n";
104 return false;
105 }
106
107 if (!base::PathExists(path->AppendASCII("extra_certs.bin"))) {
108 std::cerr
109 << "ERROR: input directory does not contain an extra_certs.bin file: "
110 << value << " \n";
111 return false;
112 }
113
114 return true;
115 }
116
117 // Make sure the output path is a directory and create a new directory for it.
118 bool GetOutputPath(const base::CommandLine::StringType& value,
119 bool clobber,
120 base::FilePath* path) {
121 // Skip output if special value "NONE" was given as the path.
122 if (value == "NONE") {
123 *path = base::FilePath();
124 std::cerr << "Will not write output directory (because specified NONE)\n";
125 return true;
126 }
127
128 // Create a temporary directory if special value "NEW" was given as the path.
129 if (value == "NEW") {
130 if (!base::CreateNewTempDirectory("ct_mapper", path)) {
131 std::cerr << "ERROR: Couldn't create new (temp) output directory.\n";
132 return false;
133 }
134
135 std::cerr << "Created output directory: " << path->value() << "\n";
136 return true;
137 }
138
139 // Otherwise use the specified path.
140 *path = base::FilePath(value);
141
142 // Make sure the path doesn't already exist.
143 if (base::PathExists(*path)) {
144 if (clobber) {
145 if (!DeleteFile(*path, true)) {
146 std::cerr << "ERROR: Failed clobbering output path: " << value << "\n";
147 return false;
148 }
149 } else {
150 std::cerr
151 << "ERROR: Output path already exists. If you want to overwrite "
152 "it anyway, pass --"
153 << kClobberSwitch
154 << " (WARNING: this is equivalent to rm -rf): " << value << "\n";
155 return false;
156 }
157 }
158
159 if (!base::CreateDirectory(*path)) {
160 std::cerr << "ERROR: Failed creating output directory: " << value << "\n";
161 return false;
162 }
163
164 return true;
165 }
166
167 WARN_UNUSED_RESULT bool ParseCommandLine(
168 const base::CommandLine& command_line,
169 std::unique_ptr<EntryReader>* reader,
170 std::unique_ptr<VisitorFactory>* visitor_factory,
171 base::FilePath* output_dir,
172 MapperOptions* options) {
173 if (command_line.GetArgs().empty()) {
174 std::cerr << "ERROR: Must specify input directory containing CT "
175 "entries.\n";
176 return false;
177 }
178
179 if (command_line.GetArgs().size() < 2) {
180 std::cerr
181 << "ERROR: Must specify an output directory for the results. If "
182 "you want to skip then use the string NONE. If you want to create a "
183 "new directory use the string NEW\n";
184 return false;
185 }
186
187 if (command_line.GetArgs().size() > 2) {
188 std::cerr << "ERROR: Too many command line parameters (expecting 2)\n";
189 return false;
190 }
191
192 base::FilePath input_path;
193
194 if (!GetInputPath(command_line.GetArgs()[0], &input_path))
195 return false;
196
197 if (!GetOutputPath(command_line.GetArgs()[1],
198 command_line.HasSwitch(kClobberSwitch), output_dir)) {
199 return false;
200 }
201
202 *reader = CreateEntryReaderForCertificateTransparencyDb(input_path);
203 if (!(*reader))
204 return false;
205
206 MapperOptions default_options;
207
208 if (!GetNumericSwitch(command_line, kNumThreadsSwitch, &options->num_threads,
209 default_options.num_threads)) {
210 return false;
211 }
212 if (!GetNumericSwitch(command_line, kNumSamplesPerBucket,
213 &options->num_samples_per_bucket,
214 default_options.num_samples_per_bucket)) {
215 return false;
216 }
217 if (!GetNumericSwitch(command_line, kChunkSizeSwitch, &options->chunk_size,
218 default_options.chunk_size)) {
219 return false;
220 }
221 if (!GetNumericSwitch(command_line, kMaxPendingChunksSwitch,
222 &options->max_pending_chunks,
223 default_options.max_pending_chunks)) {
224 return false;
225 }
226
227 size_t max_elapsed_seconds = 0;
228 if (!GetNumericSwitch(command_line, kMaxElapsedSeconds, &max_elapsed_seconds,
229 0)) {
230 return false;
231 }
232 options->max_elapsed_time = base::TimeDelta::FromSeconds(max_elapsed_seconds);
233
234 // If no output directory was specified, no point capturing any samples.
235 if (output_dir->empty()) {
236 options->num_samples_per_bucket = 0;
237 }
238
239 *visitor_factory = CreateMyVisitorFactory();
240 return *visitor_factory != nullptr;
241 }
242
243 std::string GetUsageString() {
244 MapperOptions default_options;
245 return base::StringPrintf(kUsage, default_options.num_threads,
246 default_options.num_samples_per_bucket,
247 default_options.chunk_size,
248 default_options.max_pending_chunks);
249 }
250
251 bool RunMain(const base::CommandLine& command_line) {
252 std::unique_ptr<EntryReader> reader;
253 std::unique_ptr<VisitorFactory> visitor_factory;
254 base::FilePath output_dir;
255
256 MapperOptions options;
257
258 if (!ParseCommandLine(command_line, &reader, &visitor_factory, &output_dir,
259 &options)) {
260 std::cerr << "\n" << GetUsageString();
261 return false;
262 }
263
264 Metrics metrics;
265
266 ForEachEntry(reader.get(), visitor_factory.get(), options, &metrics);
267
268 if (!output_dir.empty()) {
269 WriteResultsToDirectory(metrics, output_dir);
270 }
271
272 if (!output_dir.empty()) {
273 std::cerr << "Wrote samples and overview to:\n"
274 << output_dir.value() + "\n";
275 }
276
277 return true;
278 }
279
280 } // namespace
281
282 } // namespace net
283
284 int main(int argc, const char* argv[]) {
285 base::AtExitManager at_exit_manager;
286 base::CommandLine::Init(argc, argv);
287
288 if (!net::RunMain(*base::CommandLine::ForCurrentProcess()))
289 return -1;
290
291 return 0;
292 }
OLDNEW
« no previous file with comments | « net/tools/ct_mapper/README ('k') | net/tools/ct_mapper/dump-ct.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698