1// Copyright (c) 2012 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 "net/http/http_server_properties.h"
6
7#include "base/logging.h"
8#include "base/metrics/histogram.h"
9#include "base/strings/stringprintf.h"
10
11namespace net {
12
13const char kAlternateProtocolHeader[] = "Alternate-Protocol";
14
15namespace {
16
17// The order of these strings much match the order of the enum definition
18// for AlternateProtocol.
19const char* const kAlternateProtocolStrings[] = {
20  "npn-spdy/2",
21  "npn-spdy/3",
22  "npn-spdy/3.1",
23  "npn-h2-14",  // HTTP/2 draft 14. Called SPDY4 internally.
24  "quic"
25};
26const char kBrokenAlternateProtocol[] = "Broken";
27
28COMPILE_ASSERT(
29    arraysize(kAlternateProtocolStrings) == NUM_VALID_ALTERNATE_PROTOCOLS,
30    kAlternateProtocolStringsSize_kNumValidAlternateProtocols_not_equal);
31
32}  // namespace
33
34void HistogramAlternateProtocolUsage(
35    AlternateProtocolUsage usage,
36    AlternateProtocolExperiment alternate_protocol_experiment) {
37  UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
38                            ALTERNATE_PROTOCOL_USAGE_MAX);
39  if (alternate_protocol_experiment ==
40      ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS) {
41    UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage.200Truncated", usage,
42                              ALTERNATE_PROTOCOL_USAGE_MAX);
43  } else if (alternate_protocol_experiment ==
44      ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS) {
45    UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage.1000Truncated", usage,
46                              ALTERNATE_PROTOCOL_USAGE_MAX);
47  }
48}
49
50void HistogramBrokenAlternateProtocolLocation(
51    BrokenAlternateProtocolLocation location){
52  UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
53                            BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
54}
55
56bool IsAlternateProtocolValid(AlternateProtocol protocol) {
57  return protocol >= ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION &&
58      protocol <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION;
59}
60
61const char* AlternateProtocolToString(AlternateProtocol protocol) {
62  switch (protocol) {
63    case DEPRECATED_NPN_SPDY_2:
64    case NPN_SPDY_3:
65    case NPN_SPDY_3_1:
66    case NPN_SPDY_4:
67    case QUIC:
68      DCHECK(IsAlternateProtocolValid(protocol));
69      return kAlternateProtocolStrings[
70          protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
71    case ALTERNATE_PROTOCOL_BROKEN:
72      return kBrokenAlternateProtocol;
73    case UNINITIALIZED_ALTERNATE_PROTOCOL:
74      return "Uninitialized";
75  }
76  NOTREACHED();
77  return "";
78}
79
80AlternateProtocol AlternateProtocolFromString(const std::string& str) {
81  for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
82       i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
83    AlternateProtocol protocol = static_cast<AlternateProtocol>(i);
84    if (str == AlternateProtocolToString(protocol))
85      return protocol;
86  }
87  if (str == kBrokenAlternateProtocol)
88    return ALTERNATE_PROTOCOL_BROKEN;
89  return UNINITIALIZED_ALTERNATE_PROTOCOL;
90}
91
92AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) {
93  switch (next_proto) {
94    case kProtoDeprecatedSPDY2:
95      return DEPRECATED_NPN_SPDY_2;
96    case kProtoSPDY3:
97      return NPN_SPDY_3;
98    case kProtoSPDY31:
99      return NPN_SPDY_3_1;
100    case kProtoSPDY4:
101      return NPN_SPDY_4;
102    case kProtoQUIC1SPDY3:
103      return QUIC;
104
105    case kProtoUnknown:
106    case kProtoHTTP11:
107      break;
108  }
109
110  NOTREACHED() << "Invalid NextProto: " << next_proto;
111  return UNINITIALIZED_ALTERNATE_PROTOCOL;
112}
113
114std::string AlternateProtocolInfo::ToString() const {
115  return base::StringPrintf("%d:%s p=%f", port,
116                            AlternateProtocolToString(protocol),
117                            probability);
118}
119
120}  // namespace net
121