summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 21:17:32 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 21:17:32 +0000
commite688d9c126f890cdb361e537463265ff6345cd8d (patch)
tree4e02e48c0357cc5c2b322dbb71796c2c87c853c9
parent5d391c8d58c770e35379ce475b1831cab6e79799 (diff)
downloadchromium_src-e688d9c126f890cdb361e537463265ff6345cd8d.zip
chromium_src-e688d9c126f890cdb361e537463265ff6345cd8d.tar.gz
chromium_src-e688d9c126f890cdb361e537463265ff6345cd8d.tar.bz2
Fourth attempt at the following. Unreviewed, this was originally reviewed in http://codereview.chromium.org/7550002 .
Clean up SSL false start blacklist code. Numerous changes, including: * Handle trailing dots in LastTwoLabels() as in http://codereview.chromium.org/7518035/ . Rename this function to LastTwoComponents() to match the terminology used in the RegistryControlledDomainService and elsewhere in Chrome. * Since callers are using std::string anyway, make the functions in the header take const std::string& instead of char*. This also allows doing string operations on them. * Use string operations (like find_last_of()) in place of hand-written algorithms, for brevity, clarity, and safety. * Avoid "unsigned", which the style guide forbids, and use allowed types like size_t, uint32, or int (depending on the situation). * Avoid #define and "using". * Use standard algorithms for similar reasons as using string ops. * Use file_util functions to significantly abbreviate file reading/writing code. * Use wmain() (on Windows) in combination with FilePath to avoid issues if the provided pathname has extended characters that don't flatten losslessly to the default codepage (thanks Darin for pointing out this issue). * Avoid casting where possible. Avoid some casts for printf()-style calls by using a string stream, which also allows for slightly less boilerplate. * Convert non-error uses of stderr to the chrome-standard VLOG(1). * Correctly handle hostnames with trailing dots in the input file. * In general, shorten code where possible. Because this adds a dependency on base, and ssl_false_start_blacklist_process has the "#host" specifier in net.gyp, bradnelson tells me that base and its dependencies need an explicit "host, target" toolchain list for the Linux builds to work correctly. It would be nice if we could avoid this but I guess gyp would have to be smarter or something. BUG=none TEST=none Review URL: http://codereview.chromium.org/7903016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101378 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/base.gyp1
-rw-r--r--base/base.gypi3
-rw-r--r--base/third_party/dynamic_annotations/dynamic_annotations.gyp1
-rw-r--r--build/linux/system.gyp72
-rw-r--r--build/util/build_util.gyp1
-rw-r--r--net/base/ssl_config_service.cc2
-rw-r--r--net/base/ssl_false_start_blacklist.cc25
-rw-r--r--net/base/ssl_false_start_blacklist.h84
-rw-r--r--net/base/ssl_false_start_blacklist_process.cc377
-rw-r--r--net/base/ssl_false_start_blacklist_unittest.cc21
-rw-r--r--net/net.gyp14
-rw-r--r--third_party/libevent/libevent.gyp1
-rw-r--r--third_party/modp_b64/modp_b64.gyp1
13 files changed, 288 insertions, 315 deletions
diff --git a/base/base.gyp b/base/base.gyp
index ae754ce..30dd274 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -66,6 +66,7 @@
# base depends on base_static.
'target_name': 'base_static',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'sources': [
'base_switches.cc',
'base_switches.h',
diff --git a/base/base.gypi b/base/base.gypi
index 4b672f3..b8a2c0b 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -458,6 +458,7 @@
{
'target_name': 'base',
'type': '<(component)',
+ 'toolsets': ['host', 'target'],
'variables': {
'base_target': 1,
},
@@ -672,6 +673,7 @@
{
'target_name': 'symbolize',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'variables': {
'chromium_code': 0,
},
@@ -697,6 +699,7 @@
{
'target_name': 'xdg_mime',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'variables': {
'chromium_code': 0,
},
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.gyp b/base/third_party/dynamic_annotations/dynamic_annotations.gyp
index 47334d8..f4970ef 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.gyp
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.gyp
@@ -7,6 +7,7 @@
{
'target_name': 'dynamic_annotations',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'include_dirs': [
'../../../',
],
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 41cb824..7578552 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -31,6 +31,7 @@
{
'target_name': 'gtk',
'type': 'settings',
+ 'toolsets': ['host', 'target'],
'conditions': [
['_toolset=="target"', {
'direct_dependent_settings': {
@@ -46,12 +47,27 @@
'<!@(<(pkg-config) --libs-only-l gtk+-2.0 gthread-2.0)',
],
},
- }],
- [ 'chromeos==1', {
- 'link_settings': {
- 'libraries': [ '-lXtst' ]
- }
- }]]
+ }, {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(pkg-config --cflags gtk+-2.0 gthread-2.0)',
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(pkg-config --libs-only-L --libs-only-other gtk+-2.0 gthread-2.0)',
+ ],
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l gtk+-2.0 gthread-2.0)',
+ ],
+ },
+ }],
+ ['chromeos==1', {
+ 'link_settings': {
+ 'libraries': [ '-lXtst' ]
+ }
+ }],
+ ],
},
{
'target_name': 'gtkprint',
@@ -71,7 +87,8 @@
'<!@(<(pkg-config) --libs-only-l gtk+-unix-print-2.0)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'ssl',
@@ -148,7 +165,8 @@
'<!@(<(pkg-config) --libs-only-l freetype2)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'fontconfig',
@@ -168,7 +186,8 @@
'<!@(<(pkg-config) --libs-only-l fontconfig)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'gdk',
@@ -188,7 +207,8 @@
'<!@(<(pkg-config) --libs-only-l gdk-2.0)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'gconf',
@@ -211,7 +231,8 @@
'<!@(<(pkg-config) --libs-only-l gconf-2.0)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'gio',
@@ -246,11 +267,13 @@
}],
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'x11',
'type': 'settings',
+ 'toolsets': ['host', 'target'],
'conditions': [
['_toolset=="target"', {
'direct_dependent_settings': {
@@ -266,7 +289,21 @@
'<!@(<(pkg-config) --libs-only-l x11 xi)',
],
},
- }],
+ }, {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(pkg-config --cflags x11)',
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(pkg-config --libs-only-L --libs-only-other x11 xi)',
+ ],
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l x11 xi)',
+ ],
+ },
+ }],
],
},
{
@@ -287,7 +324,8 @@
'<!@(<(pkg-config) --libs-only-l xext)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'libgcrypt',
@@ -304,7 +342,8 @@
'<!@(libgcrypt-config --libs)',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'selinux',
@@ -316,7 +355,8 @@
'-lselinux',
],
},
- }]]
+ }],
+ ],
},
{
'target_name': 'gnome_keyring',
diff --git a/build/util/build_util.gyp b/build/util/build_util.gyp
index afbbd81..0053776 100644
--- a/build/util/build_util.gyp
+++ b/build/util/build_util.gyp
@@ -7,6 +7,7 @@
{
'target_name': 'lastchange',
'type': 'none',
+ 'toolsets': ['host', 'target'],
'variables': {
'lastchange_out_path': '<(SHARED_INTERMEDIATE_DIR)/build/LASTCHANGE',
'default_lastchange_path': '../LASTCHANGE.in',
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index c7153e3..29e1b79 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -52,7 +52,7 @@ SSLConfigService::SSLConfigService()
// static
bool SSLConfigService::IsKnownFalseStartIncompatibleServer(
const std::string& hostname) {
- return SSLFalseStartBlacklist::IsMember(hostname.c_str());
+ return SSLFalseStartBlacklist::IsMember(hostname);
}
static bool g_cached_info_enabled = false;
diff --git a/net/base/ssl_false_start_blacklist.cc b/net/base/ssl_false_start_blacklist.cc
index b57826b..d08852d 100644
--- a/net/base/ssl_false_start_blacklist.cc
+++ b/net/base/ssl_false_start_blacklist.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -7,22 +7,19 @@
namespace net {
// static
-bool SSLFalseStartBlacklist::IsMember(const char* host) {
- const char* last_two_labels = LastTwoLabels(host);
- if (!last_two_labels)
+bool SSLFalseStartBlacklist::IsMember(const std::string& host) {
+ const std::string last_two_components(LastTwoComponents(host));
+ if (last_two_components.empty())
return false;
- const unsigned bucket = Hash(last_two_labels) & (kBuckets - 1);
- const uint32 start = kHashTable[bucket];
- const uint32 end = kHashTable[bucket + 1];
- const size_t len = strlen(host);
- for (size_t i = start; i < end;) {
+ const size_t bucket = Hash(last_two_components) & (kBuckets - 1);
+ for (size_t i = kHashTable[bucket]; i < kHashTable[bucket + 1]; ) {
const size_t blacklist_entry_len = static_cast<uint8>(kHashData[i]);
- if (len >= blacklist_entry_len &&
- memcmp(&host[len - blacklist_entry_len], &kHashData[i + 1],
- blacklist_entry_len) == 0 &&
- (len == blacklist_entry_len ||
- host[len - blacklist_entry_len - 1] == '.')) {
+ if (host.length() >= blacklist_entry_len &&
+ !host.compare(host.length() - blacklist_entry_len, blacklist_entry_len,
+ &kHashData[i + 1], blacklist_entry_len) &&
+ (host.length() == blacklist_entry_len ||
+ host[host.length() - blacklist_entry_len - 1] == '.')) {
return true;
}
i += blacklist_entry_len + 1;
diff --git a/net/base/ssl_false_start_blacklist.h b/net/base/ssl_false_start_blacklist.h
index 3d31702..ad7a007 100644
--- a/net/base/ssl_false_start_blacklist.h
+++ b/net/base/ssl_false_start_blacklist.h
@@ -5,7 +5,9 @@
#ifndef NET_BASE_SSL_FALSE_START_BLACKLIST_H_
#define NET_BASE_SSL_FALSE_START_BLACKLIST_H_
-#include "base/basictypes.h"
+#include <string>
+
+#include "base/logging.h"
#include "net/base/net_export.h"
namespace net {
@@ -16,64 +18,42 @@ namespace net {
// table for fast lookups.
class SSLFalseStartBlacklist {
public:
- // IsMember returns true if the given host is in the blacklist.
- // host: a DNS name in dotted form (i.e. "www.example.com")
- NET_EXPORT_PRIVATE static bool IsMember(const char* host);
-
- // Hash returns the modified djb2 hash of the given string.
- static unsigned Hash(const char* str) {
- // This is inline because the code which generates the hash table needs to
- // use it. However, the generating code cannot link against
- // ssl_false_start_blacklist.cc because that needs the tables which it
- // generates.
- const unsigned char* in = reinterpret_cast<const unsigned char*>(str);
- unsigned hash = 5381;
- unsigned char c;
-
- while ((c = *in++))
- hash = ((hash << 5) + hash) ^ c;
+ // Returns true if |host| (a DNS name in dotted form, e.g. "www.example.com")
+ // is in the blacklist.
+ NET_EXPORT_PRIVATE static bool IsMember(const std::string& host);
+
+ // Returns the modified djb2 hash of |host|.
+ // NOTE: This is inline because the code which generates the hash table needs
+ // to use it. However, the generating code cannot link against
+ // ssl_false_start_blacklist.cc because that needs the tables which it
+ // generates.
+ static uint32 Hash(const std::string& host) {
+ uint32 hash = 5381;
+ for (const uint8* in = reinterpret_cast<const uint8*>(host.c_str());
+ *in != 0; ++in)
+ hash = ((hash << 5) + hash) ^ *in;
return hash;
}
- // LastTwoLabels returns a pointer within |host| to the last two labels of
- // |host|. For example, if |host| is "a.b.c.d" then LastTwoLabels will return
- // "c.d".
- // host: a DNS name in dotted form.
- // returns: NULL on error, otherwise a pointer inside |host|.
- static const char* LastTwoLabels(const char* host) {
- // See comment in |Hash| for why this function is inline.
- const size_t len = strlen(host);
- if (len == 0)
- return NULL;
-
- unsigned dots_found = 0;
- size_t i;
- for (i = len - 1; i < len; i--) {
- if (host[i] == '.') {
- dots_found++;
- if (dots_found == 2) {
- i++;
- break;
- }
- }
- }
-
- if (i > len)
- i = 0;
-
- if (dots_found == 0)
- return NULL; // no names with less than two labels are in the blacklist.
- if (dots_found == 1) {
- if (host[0] == '.')
- return NULL; // ditto
- }
-
- return &host[i];
+ // Returns the last two dot-separated components of |host|, ignoring any
+ // trailing dots. For example, returns "c.d" for "a.b.c.d.". Returns an
+ // empty string if |host| does not have two dot-separated components.
+ // NOTE: Inline for the same reason as Hash().
+ static std::string LastTwoComponents(const std::string& host) {
+ size_t last_nondot = host.find_last_not_of('.');
+ if (last_nondot == std::string::npos)
+ return std::string();
+ size_t last_dot = host.find_last_of('.', last_nondot);
+ if ((last_dot == 0) || (last_dot == std::string::npos))
+ return std::string();
+ // NOTE: This next line works correctly even when the call returns npos.
+ size_t components_begin = host.find_last_of('.', last_dot - 1) + 1;
+ return host.substr(components_begin, last_nondot - components_begin + 1);
}
// This is the number of buckets in the blacklist hash table. (Must be a
// power of two).
- static const unsigned kBuckets = 128;
+ static const size_t kBuckets = 128;
private:
// The following two members are defined in
diff --git a/net/base/ssl_false_start_blacklist_process.cc b/net/base/ssl_false_start_blacklist_process.cc
index 762a665..e1ff7d2 100644
--- a/net/base/ssl_false_start_blacklist_process.cc
+++ b/net/base/ssl_false_start_blacklist_process.cc
@@ -5,116 +5,115 @@
// This utility program exists to process the False Start blacklist file into
// a static hash table so that it can be efficiently queried by Chrome.
-#include <stdio.h>
-#include <stdlib.h>
-
+#include <algorithm>
+#include <cstdio>
#include <set>
+#include <sstream>
#include <string>
#include <vector>
#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/string_util.h"
#include "net/base/ssl_false_start_blacklist.h"
-using net::SSLFalseStartBlacklist;
-
-static const unsigned kBuckets = SSLFalseStartBlacklist::kBuckets;
-
-static bool verbose = false;
-
-static int
-usage(const char* argv0) {
- fprintf(stderr, "Usage: %s <blacklist file> <output .c file>\n", argv0);
- return 1;
-}
-
-// StripWWWPrefix removes "www." from the beginning of any elements of the
-// vector.
-static void StripWWWPrefix(std::vector<std::string>* hosts) {
- static const char kPrefix[] = "www.";
- static const unsigned kPrefixLen = sizeof(kPrefix) - 1;
+typedef std::vector<std::string> Hosts;
- for (size_t i = 0; i < hosts->size(); i++) {
- const std::string& h = (*hosts)[i];
- if (h.size() >= kPrefixLen &&
- memcmp(h.data(), kPrefix, kPrefixLen) == 0) {
- (*hosts)[i] = h.substr(kPrefixLen, h.size() - kPrefixLen);
+// Parses |input| as a blacklist data file, and returns the set of hosts it
+// contains.
+Hosts ParseHosts(const std::string& input) {
+ Hosts hosts;
+ size_t line_start = 0;
+ bool is_comment = false;
+ bool non_whitespace_seen = false;
+ for (size_t i = 0; i <= input.size(); ++i) {
+ if (i == input.size() || input[i] == '\n') {
+ if (!is_comment && non_whitespace_seen) {
+ size_t len = i - line_start;
+ if (i > 0 && input[i - 1] == '\r')
+ len--;
+ hosts.push_back(input.substr(line_start, len));
+ }
+ is_comment = false;
+ non_whitespace_seen = false;
+ line_start = i + 1;
+ } else if (input[i] != ' ' && input[i] != '\t' && input[i] != '\r') {
+ non_whitespace_seen = true;
+ if (i == line_start && input[i] == '#')
+ is_comment = true;
}
}
+ VLOG(1) << "Have " << hosts.size() << " hosts after parse";
+ return hosts;
}
-// RemoveDuplicateEntries removes all duplicates from |hosts|.
-static void RemoveDuplicateEntries(std::vector<std::string>* hosts) {
- std::set<std::string> hosts_set;
- std::vector<std::string> ret;
+// Returns |host| with any initial "www." and trailing dots removed. Partly
+// based on net::StripWWW().
+std::string StripWWWAndTrailingDots(const std::string& host) {
+ const std::string www("www.");
+ const size_t start = StartsWithASCII(host, www, true) ? www.length() : 0;
+ const size_t end = host.find_last_not_of('.');
+ return (end == std::string::npos) ?
+ std::string() : host.substr(start, end - start + 1);
+}
- for (std::vector<std::string>::const_iterator
- i = hosts->begin(); i != hosts->end(); i++) {
- if (hosts_set.count(*i)) {
- if (verbose)
- fprintf(stderr, "Removing duplicate entry for %s\n", i->c_str());
- continue;
- }
- hosts_set.insert(*i);
- ret.push_back(*i);
- }
+// Removes all duplicates from |hosts|.
+static void RemoveDuplicateEntries(std::vector<std::string>* hosts) {
+ std::sort(hosts->begin(), hosts->end());
+ hosts->erase(std::unique(hosts->begin(), hosts->end()), hosts->end());
+ VLOG(1) << "Have " << hosts->size() << " hosts after removing duplicates";
+}
- hosts->swap(ret);
+// Returns the parent domain for |host|, or the empty string if the name is a
+// top-level domain.
+static std::string ParentDomain(const std::string& host) {
+ const size_t first_dot = host.find('.');
+ return (first_dot == std::string::npos) ?
+ std::string() : host.substr(first_dot + 1);
}
-// ParentDomain returns the parent domain for a given domain name or the empty
-// string if the name is a top-level domain.
-static std::string ParentDomain(const std::string& in) {
- for (size_t i = 0; i < in.size(); i++) {
- if (in[i] == '.') {
- return in.substr(i + 1, in.size() - i - 1);
+// Predicate which returns true when a hostname has a parent domain in the set
+// of hosts provided at construction time.
+class ParentInSet : public std::unary_function<std::string, bool> {
+ public:
+ explicit ParentInSet(const std::set<std::string>& hosts) : hosts_(hosts) {}
+
+ bool operator()(const std::string& host) const {
+ for (std::string parent(ParentDomain(host)); !parent.empty();
+ parent = ParentDomain(parent)) {
+ if (hosts_.count(parent)) {
+ VLOG(1) << "Removing " << host << " as redundant";
+ return true;
+ }
}
+ return false;
}
- return std::string();
-}
+ private:
+ const std::set<std::string>& hosts_;
+};
-// RemoveRedundantEntries removes any entries which are subdomains of other
-// entries. (i.e. foo.example.com would be removed if example.com were also
-// included.)
-static void RemoveRedundantEntries(std::vector<std::string>* hosts) {
+// Removes any hosts which are subdomains of other hosts. E.g.
+// "foo.example.com" would be removed if "example.com" were also included.
+static void RemoveRedundantEntries(Hosts* hosts) {
std::set<std::string> hosts_set;
- std::vector<std::string> ret;
-
- for (std::vector<std::string>::const_iterator
- i = hosts->begin(); i != hosts->end(); i++) {
+ for (Hosts::const_iterator i(hosts->begin()); i != hosts->end(); ++i)
hosts_set.insert(*i);
- }
-
- for (std::vector<std::string>::const_iterator
- i = hosts->begin(); i != hosts->end(); i++) {
- std::string parent = ParentDomain(*i);
- while (!parent.empty()) {
- if (hosts_set.count(parent))
- break;
- parent = ParentDomain(parent);
- }
- if (parent.empty()) {
- ret.push_back(*i);
- } else {
- if (verbose)
- fprintf(stderr, "Removing %s as redundant\n", i->c_str());
- }
- }
-
- hosts->swap(ret);
+ hosts->erase(std::remove_if(hosts->begin(), hosts->end(),
+ ParentInSet(hosts_set)), hosts->end());
+ VLOG(1) << "Have " << hosts->size() << " hosts after removing redundants";
}
-// CheckLengths returns true iff every host is less than 256 bytes long (not
-// including the terminating NUL) and contains two or more labels.
-static bool CheckLengths(const std::vector<std::string>& hosts) {
- for (std::vector<std::string>::const_iterator
- i = hosts.begin(); i != hosts.end(); i++) {
+// Returns true iff all |hosts| are less than 256 bytes long (not including the
+// terminating NUL) and contain two or more dot-separated components.
+static bool CheckLengths(const Hosts& hosts) {
+ for (Hosts::const_iterator i(hosts.begin()); i != hosts.end(); ++i) {
if (i->size() >= 256) {
- fprintf(stderr, "Entry %s is too large\n", i->c_str());
+ fprintf(stderr, "Entry '%s' is too large\n", i->c_str());
return false;
}
- if (SSLFalseStartBlacklist::LastTwoLabels(i->c_str()) == NULL) {
- fprintf(stderr, "Entry %s contains too few labels\n", i->c_str());
+ if (net::SSLFalseStartBlacklist::LastTwoComponents(*i).empty()) {
+ fprintf(stderr, "Entry '%s' contains too few labels\n", i->c_str());
return false;
}
}
@@ -122,150 +121,94 @@ static bool CheckLengths(const std::vector<std::string>& hosts) {
return true;
}
-int main(int argc, char** argv) {
- if (argc != 3)
- return usage(argv[0]);
-
- const char* input_file = argv[1];
- const char* output_file = argv[2];
- FILE* input = fopen(input_file, "rb");
- if (!input) {
- perror("open");
- return usage(argv[0]);
- }
-
- if (fseek(input, 0, SEEK_END)) {
- perror("fseek");
- return 1;
- }
-
- const long input_size = ftell(input);
- if (input_size < 0) {
- perror("ftell");
- return 1;
- }
-
- if (fseek(input, 0, SEEK_SET)) {
- perror("fseek");
- return 1;
- }
-
- char* buffer = static_cast<char*>(malloc(input_size));
- long done = 0;
- while (done < input_size) {
- size_t n = fread(buffer + done, 1, input_size - done, input);
- if (n == 0) {
- perror("fread");
- free(buffer);
- fclose(input);
- return 1;
- }
- done += n;
- }
- fclose(input);
-
- std::vector<std::string> hosts;
-
- off_t line_start = 0;
- bool is_comment = false;
- bool non_whitespace_seen = false;
- for (long i = 0; i <= input_size; i++) {
- if (i == input_size || buffer[i] == '\n') {
- if (!is_comment && non_whitespace_seen) {
- long len = i - line_start;
- if (i > 0 && buffer[i-1] == '\r')
- len--;
- hosts.push_back(std::string(&buffer[line_start], len));
- }
- is_comment = false;
- non_whitespace_seen = false;
- line_start = i + 1;
- continue;
- }
-
- if (i == line_start && buffer[i] == '#')
- is_comment = true;
- if (buffer[i] != ' ' && buffer[i] != '\t' && buffer[i] != '\r')
- non_whitespace_seen = true;
- }
- free(buffer);
-
- fprintf(stderr, "Have %d hosts after parse\n", (int) hosts.size());
- StripWWWPrefix(&hosts);
- RemoveDuplicateEntries(&hosts);
- fprintf(stderr, "Have %d hosts after removing duplicates\n", (int) hosts.size());
- RemoveRedundantEntries(&hosts);
- fprintf(stderr, "Have %d hosts after removing redundants\n", (int) hosts.size());
- if (!CheckLengths(hosts)) {
- fprintf(stderr, "One or more entries is too large or too small\n");
- return 2;
- }
-
- fprintf(stderr, "Using %d entry hash table\n", kBuckets);
- uint32 table[kBuckets];
- std::vector<std::string> buckets[kBuckets];
-
- for (std::vector<std::string>::const_iterator
- i = hosts.begin(); i != hosts.end(); i++) {
- const char* last_two_labels =
- SSLFalseStartBlacklist::LastTwoLabels(i->c_str());
- const unsigned h = SSLFalseStartBlacklist::Hash(last_two_labels);
- buckets[h & (kBuckets - 1)].push_back(*i);
- }
-
+// Returns the contents of the output file to be written.
+std::string GenerateOutput(const Hosts& hosts) {
+ // Hash each host into its appropriate bucket.
+ VLOG(1) << "Using " << net::SSLFalseStartBlacklist::kBuckets
+ << " entry hash table";
+ Hosts buckets[net::SSLFalseStartBlacklist::kBuckets];
+ for (Hosts::const_iterator i(hosts.begin()); i != hosts.end(); ++i) {
+ const uint32 hash = net::SSLFalseStartBlacklist::Hash(
+ net::SSLFalseStartBlacklist::LastTwoComponents(*i));
+ buckets[hash & (net::SSLFalseStartBlacklist::kBuckets - 1)].push_back(*i);
+ }
+
+ // Write header.
+ std::ostringstream output;
+ output << "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n"
+ "// Use of this source code is governed by a BSD-style license that"
+ " can be\n// found in the LICENSE file.\n\n// WARNING: This code is"
+ " generated by ssl_false_start_blacklist_process.cc.\n// Do not "
+ "edit.\n\n#include \"net/base/ssl_false_start_blacklist.h\"\n\n"
+ "namespace net {\n\nconst uint32 "
+ "SSLFalseStartBlacklist::kHashTable["
+ << net::SSLFalseStartBlacklist::kBuckets << " + 1] = {\n 0,\n";
+
+ // Construct data table, writing out the size as each bucket is appended.
std::string table_data;
- unsigned max_bucket_size = 0;
- for (unsigned i = 0; i < kBuckets; i++) {
- if (buckets[i].size() > max_bucket_size)
- max_bucket_size = buckets[i].size();
-
- table[i] = table_data.size();
- for (std::vector<std::string>::const_iterator
- j = buckets[i].begin(); j != buckets[i].end(); j++) {
- table_data.push_back((char) j->size());
+ size_t max_bucket_size = 0;
+ for (size_t i = 0; i < net::SSLFalseStartBlacklist::kBuckets; i++) {
+ max_bucket_size = std::max(max_bucket_size, buckets[i].size());
+ for (Hosts::const_iterator j(buckets[i].begin()); j != buckets[i].end();
+ ++j) {
+ table_data.push_back(static_cast<char>(j->size()));
table_data.append(*j);
}
+ output << " " << table_data.size() << ",\n";
}
+ output << "};\n\n";
+ VLOG(1) << "Largest bucket has " << max_bucket_size << " entries";
- fprintf(stderr, "Largest bucket has %d entries\n", max_bucket_size);
-
- FILE* out = fopen(output_file, "w+");
- if (!out) {
- perror("opening output file");
- return 4;
- }
-
- fprintf(out, "// Copyright (c) 2010 The Chromium Authors. All rights "
- "reserved.\n// Use of this source code is governed by a BSD-style "
- "license that can be\n// found in the LICENSE file.\n\n");
- fprintf(out, "// WARNING: this code is generated by\n"
- "// ssl_false_start_blacklist_process.cc. Do not edit.\n\n");
- fprintf(out, "#include \"base/basictypes.h\"\n\n");
- fprintf(out, "#include \"net/base/ssl_false_start_blacklist.h\"\n\n");
- fprintf(out, "namespace net {\n\n");
- fprintf(out, "const uint32 SSLFalseStartBlacklist::kHashTable[%d + 1] = {\n",
- kBuckets);
- for (unsigned i = 0; i < kBuckets; i++) {
- fprintf(out, " %u,\n", (unsigned) table[i]);
- }
- fprintf(out, " %u,\n", (unsigned) table_data.size());
- fprintf(out, "};\n\n");
-
- fprintf(out, "const char SSLFalseStartBlacklist::kHashData[] = {\n");
- for (unsigned i = 0, line_length = 0; i < table_data.size(); i++) {
+ // Write data table, breaking lines after 72+ (2 indent, 70+ data) characters.
+ output << "const char SSLFalseStartBlacklist::kHashData[] = {\n";
+ for (size_t i = 0, line_length = 0; i < table_data.size(); i++) {
if (line_length == 0)
- fprintf(out, " ");
- uint8 c = static_cast<uint8>(table_data[i]);
- line_length += fprintf(out, "%d, ", c);
+ output << " ";
+ std::ostringstream::pos_type current_length = output.tellp();
+ output << static_cast<int>(table_data[i]) << ", ";
+ line_length += output.tellp() - current_length;
if (i == table_data.size() - 1) {
- fprintf(out, "\n};\n");
+ output << "\n};\n";
} else if (line_length >= 70) {
- fprintf(out, "\n");
+ output << "\n";
line_length = 0;
}
}
- fprintf(out, "\n} // namespace net\n");
- fclose(out);
+ output << "\n} // namespace net\n";
+ return output.str();
+}
+
+#if defined(OS_WIN)
+int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) {
+#elif defined(OS_POSIX)
+int main(int argc, char* argv[], char* envp[]) {
+#endif
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <blacklist file> <output .c file>\n", argv[0]);
+ return 1;
+ }
- return 0;
+ // Read input file.
+ std::string input;
+ if (!file_util::ReadFileToString(FilePath(argv[1]), &input)) {
+ fprintf(stderr, "Failed to read input file '%s'\n", argv[1]);
+ return 2;
+ }
+ Hosts hosts(ParseHosts(input));
+
+ // Sanitize |hosts|.
+ std::transform(hosts.begin(), hosts.end(), hosts.begin(),
+ StripWWWAndTrailingDots);
+ RemoveDuplicateEntries(&hosts);
+ RemoveRedundantEntries(&hosts);
+ if (!CheckLengths(hosts))
+ return 3;
+
+ // Write output file.
+ const std::string output_str(GenerateOutput(hosts));
+ if (file_util::WriteFile(FilePath(argv[2]), output_str.data(),
+ output_str.size()) == static_cast<int>(output_str.size()))
+ return 0;
+ fprintf(stderr, "Failed to write output file '%s'\n", argv[2]);
+ return 4;
}
diff --git a/net/base/ssl_false_start_blacklist_unittest.cc b/net/base/ssl_false_start_blacklist_unittest.cc
index 7eedae4..9dad42c 100644
--- a/net/base/ssl_false_start_blacklist_unittest.cc
+++ b/net/base/ssl_false_start_blacklist_unittest.cc
@@ -7,18 +7,17 @@
namespace net {
-TEST(SSLFalseStartBlacklistTest, LastTwoLabels) {
-#define F SSLFalseStartBlacklist::LastTwoLabels
- EXPECT_STREQ(F("a.b.c.d"), "c.d");
- EXPECT_STREQ(F("a.b"), "a.b");
- EXPECT_STREQ(F("example.com"), "example.com");
- EXPECT_STREQ(F("www.example.com"), "example.com");
- EXPECT_STREQ(F("www.www.example.com"), "example.com");
+TEST(SSLFalseStartBlacklistTest, LastTwoComponents) {
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("a.b.c.d"), "c.d");
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("a.b"), "a.b");
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("www.a.de"), "a.de");
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("www.www.a.de"), "a.de");
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("a.com."), "a.com");
+ EXPECT_EQ(SSLFalseStartBlacklist::LastTwoComponents("a.com.."), "a.com");
- EXPECT_TRUE(F("com") == NULL);
- EXPECT_TRUE(F(".com") == NULL);
- EXPECT_TRUE(F("") == NULL);
-#undef F
+ EXPECT_TRUE(SSLFalseStartBlacklist::LastTwoComponents("com").empty());
+ EXPECT_TRUE(SSLFalseStartBlacklist::LastTwoComponents(".com").empty());
+ EXPECT_TRUE(SSLFalseStartBlacklist::LastTwoComponents("").empty());
}
TEST(SSLFalseStartBlacklistTest, IsMember) {
diff --git a/net/net.gyp b/net/net.gyp
index dc928cd..61e6af9 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -209,6 +209,7 @@
'base/ssl_config_service_defaults.cc',
'base/ssl_config_service_defaults.h',
'base/ssl_false_start_blacklist.cc',
+ 'base/ssl_false_start_blacklist.h',
'base/ssl_info.cc',
'base/ssl_info.h',
'base/static_cookie_policy.cc',
@@ -1399,11 +1400,16 @@
'target_name': 'ssl_false_start_blacklist_process',
'type': 'executable',
'toolsets': ['host'],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ ],
'include_dirs': [
'..',
],
'sources': [
'base/ssl_false_start_blacklist_process.cc',
+ 'base/ssl_false_start_blacklist.h',
],
},
],
@@ -1418,7 +1424,7 @@
],
'dependencies': [
'../base/base.gyp:base',
- 'net.gyp:net',
+ 'net',
'../third_party/openssl/openssl.gyp:openssl',
],
'sources': [
@@ -1480,7 +1486,7 @@
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
- 'net.gyp:net',
+ 'net',
],
'sources': [
'curvecp/circular_buffer.cc',
@@ -1515,8 +1521,8 @@
'type': 'executable',
'dependencies': [
'../base/base.gyp:base',
- 'net.gyp:curvecp',
- 'net.gyp:net',
+ 'curvecp',
+ 'net',
'net_test_support',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
diff --git a/third_party/libevent/libevent.gyp b/third_party/libevent/libevent.gyp
index f4c9be0..55b19cd 100644
--- a/third_party/libevent/libevent.gyp
+++ b/third_party/libevent/libevent.gyp
@@ -13,6 +13,7 @@
'target_name': 'libevent',
'product_name': 'event',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'sources': [
'buffer.c',
'evbuffer.c',
diff --git a/third_party/modp_b64/modp_b64.gyp b/third_party/modp_b64/modp_b64.gyp
index 35c0a99..baed111 100644
--- a/third_party/modp_b64/modp_b64.gyp
+++ b/third_party/modp_b64/modp_b64.gyp
@@ -7,6 +7,7 @@
{
'target_name': 'modp_b64',
'type': 'static_library',
+ 'toolsets': ['host', 'target'],
'sources': [
'modp_b64.cc',
'modp_b64.h',