13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be
33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file.
43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This utility program exists to process the False Start blacklist file into
63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a static hash table so that it can be efficiently queried by Chrome.
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <stdio.h>
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <stdlib.h>
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <set>
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <string>
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <vector>
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/basictypes.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/ssl_false_start_blacklist.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickusing net::SSLFalseStartBlacklist;
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const unsigned kBuckets = SSLFalseStartBlacklist::kBuckets;
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic bool verbose = false;
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic int
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickusage(const char* argv0) {
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Usage: %s <blacklist file> <output .c file>\n", argv0);
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return 1;
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// StripWWWPrefix removes "www." from the beginning of any elements of the
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// vector.
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void StripWWWPrefix(std::vector<std::string>* hosts) {
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPrefix[] = "www.";
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned kPrefixLen = sizeof(kPrefix) - 1;
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (size_t i = 0; i < hosts->size(); i++) {
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& h = (*hosts)[i];
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (h.size() >= kPrefixLen &&
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        memcmp(h.data(), kPrefix, kPrefixLen) == 0) {
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      (*hosts)[i] = h.substr(kPrefixLen, h.size() - kPrefixLen);
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// RemoveDuplicateEntries removes all duplicates from |hosts|.
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void RemoveDuplicateEntries(std::vector<std::string>* hosts) {
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::set<std::string> hosts_set;
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<std::string> ret;
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::vector<std::string>::const_iterator
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i = hosts->begin(); i != hosts->end(); i++) {
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (hosts_set.count(*i)) {
53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (verbose)
54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        fprintf(stderr, "Removing duplicate entry for %s\n", i->c_str());
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    hosts_set.insert(*i);
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret.push_back(*i);
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hosts->swap(ret);
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ParentDomain returns the parent domain for a given domain name or the empty
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// string if the name is a top-level domain.
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic std::string ParentDomain(const std::string& in) {
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (size_t i = 0; i < in.size(); i++) {
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (in[i] == '.') {
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return in.substr(i + 1, in.size() - i - 1);
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return std::string();
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// RemoveRedundantEntries removes any entries which are subdomains of other
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// entries. (i.e. foo.example.com would be removed if example.com were also
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// included.)
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void RemoveRedundantEntries(std::vector<std::string>* hosts) {
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::set<std::string> hosts_set;
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<std::string> ret;
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::vector<std::string>::const_iterator
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i = hosts->begin(); i != hosts->end(); i++) {
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    hosts_set.insert(*i);
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::vector<std::string>::const_iterator
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i = hosts->begin(); i != hosts->end(); i++) {
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string parent = ParentDomain(*i);
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    while (!parent.empty()) {
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (hosts_set.count(parent))
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      parent = ParentDomain(parent);
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (parent.empty()) {
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ret.push_back(*i);
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (verbose)
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        fprintf(stderr, "Removing %s as redundant\n", i->c_str());
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hosts->swap(ret);
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// CheckLengths returns true iff every host is less than 256 bytes long (not
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// including the terminating NUL) and contains two or more labels.
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic bool CheckLengths(const std::vector<std::string>& hosts) {
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::vector<std::string>::const_iterator
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i = hosts.begin(); i != hosts.end(); i++) {
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     if (i->size() >= 256) {
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       fprintf(stderr, "Entry %s is too large\n", i->c_str());
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       return false;
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     }
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     if (SSLFalseStartBlacklist::LastTwoLabels(i->c_str()) == NULL) {
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       fprintf(stderr, "Entry %s contains too few labels\n", i->c_str());
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       return false;
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     }
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint main(int argc, char** argv) {
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (argc != 3)
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return usage(argv[0]);
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* input_file = argv[1];
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* output_file = argv[2];
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  FILE* input = fopen(input_file, "rb");
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!input) {
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    perror("open");
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return usage(argv[0]);
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (fseek(input, 0, SEEK_END)) {
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    perror("fseek");
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 1;
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const long input_size = ftell(input);
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (fseek(input, 0, SEEK_SET)) {
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    perror("fseek");
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 1;
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char* buffer = static_cast<char*>(malloc(input_size));
150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  long done = 0;
151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  while (done < input_size) {
152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    size_t n = fread(buffer + done, 1, input_size - done, input);
153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (n == 0) {
154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      perror("fread");
155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      free(buffer);
156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      fclose(input);
157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return 1;
158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    done += n;
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fclose(input);
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<std::string> hosts;
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  off_t line_start = 0;
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool is_comment = false;
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool non_whitespace_seen = false;
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (long i = 0; i <= input_size; i++) {
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i == input_size || buffer[i] == '\n') {
170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (!is_comment && non_whitespace_seen) {
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        long len = i - line_start;
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        if (i > 0 && buffer[i-1] == '\r')
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          len--;
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        hosts.push_back(std::string(&buffer[line_start], len));
175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      is_comment = false;
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      non_whitespace_seen = false;
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      line_start = i + 1;
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i == line_start && buffer[i] == '#')
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      is_comment = true;
184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (buffer[i] != ' ' && buffer[i] != '\t' && buffer[i] != '\r')
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      non_whitespace_seen = true;
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  free(buffer);
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Have %d hosts after parse\n", (int) hosts.size());
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StripWWWPrefix(&hosts);
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  RemoveDuplicateEntries(&hosts);
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Have %d hosts after removing duplicates\n", (int) hosts.size());
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  RemoveRedundantEntries(&hosts);
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Have %d hosts after removing redundants\n", (int) hosts.size());
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!CheckLengths(hosts)) {
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    fprintf(stderr, "One or more entries is too large or too small\n");
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 2;
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Using %d entry hash table\n", kBuckets);
201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  uint32 table[kBuckets];
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<std::string> buckets[kBuckets];
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::vector<std::string>::const_iterator
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i = hosts.begin(); i != hosts.end(); i++) {
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const char* last_two_labels =
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        SSLFalseStartBlacklist::LastTwoLabels(i->c_str());
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const unsigned h = SSLFalseStartBlacklist::Hash(last_two_labels);
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buckets[h & (kBuckets - 1)].push_back(*i);
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string table_data;
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  unsigned max_bucket_size = 0;
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (unsigned i = 0; i < kBuckets; i++) {
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (buckets[i].size() > max_bucket_size)
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      max_bucket_size = buckets[i].size();
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    table[i] = table_data.size();
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (std::vector<std::string>::const_iterator
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick         j = buckets[i].begin(); j != buckets[i].end(); j++) {
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      table_data.push_back((char) j->size());
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      table_data.append(*j);
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(stderr, "Largest bucket has %d entries\n", max_bucket_size);
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FILE* out = fopen(output_file, "w+");
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!out) {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    perror("opening output file");
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 4;
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "// Copyright (c) 2010 The Chromium Authors. All rights "
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          "reserved.\n// Use of this source code is governed by a BSD-style "
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          "license that can be\n// found in the LICENSE file.\n\n");
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "// WARNING: this code is generated by\n"
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               "// ssl_false_start_blacklist_process.cc. Do not edit.\n\n");
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "#include \"base/basictypes.h\"\n\n");
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "#include \"net/base/ssl_false_start_blacklist.h\"\n\n");
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "namespace net {\n\n");
242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  fprintf(out, "const uint32 SSLFalseStartBlacklist::kHashTable[%d + 1] = {\n",
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          kBuckets);
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (unsigned i = 0; i < kBuckets; i++) {
245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    fprintf(out, "  %u,\n", (unsigned) table[i]);
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  fprintf(out, "  %u,\n", (unsigned) table_data.size());
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "};\n\n");
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  fprintf(out, "const char SSLFalseStartBlacklist::kHashData[] = {\n");
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (unsigned i = 0, line_length = 0; i < table_data.size(); i++) {
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (line_length == 0)
253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      fprintf(out, "  ");
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    uint8 c = static_cast<uint8>(table_data[i]);
255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    line_length += fprintf(out, "%d, ", c);
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i == table_data.size() - 1) {
257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      fprintf(out, "\n};\n");
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (line_length >= 70) {
259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      fprintf(out, "\n");
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      line_length = 0;
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fprintf(out, "\n}  // namespace net\n");
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fclose(out);
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return 0;
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
268