Index: net/spdy/spdy_alt_svc_wire_format.cc |
diff --git a/net/spdy/spdy_alt_svc_wire_format.cc b/net/spdy/spdy_alt_svc_wire_format.cc |
index cc68e87d1f8eeb2b16ec01d17a2b3bfba2927ff3..0c1756b8a8116301e59a36cf930ad0c74ea334a5 100644 |
--- a/net/spdy/spdy_alt_svc_wire_format.cc |
+++ b/net/spdy/spdy_alt_svc_wire_format.cc |
@@ -40,15 +40,17 @@ SpdyAltSvcWireFormat::AlternativeService::AlternativeService( |
const std::string& protocol_id, |
const std::string& host, |
uint16 port, |
- uint16 version, |
uint32 max_age, |
- double probability) |
+ double probability, |
+ VersionVector version) |
: protocol_id(protocol_id), |
host(host), |
port(port), |
- version(version), |
max_age(max_age), |
- probability(probability) {} |
+ probability(probability), |
+ version(version) {} |
+ |
+SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {} |
// static |
bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
@@ -105,9 +107,9 @@ bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
} |
++c; |
// Parse parameters. |
- uint16 version = 0; |
uint32 max_age = 86400; |
double probability = 1.0; |
+ VersionVector version; |
StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); |
while (c != parameters_end) { |
SkipWhiteSpace(&c, parameters_end); |
@@ -138,11 +140,7 @@ bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
if (c == parameter_value_begin) { |
return false; |
} |
- if (parameter_name.compare("v") == 0) { |
- if (!ParsePositiveInteger16(parameter_value_begin, c, &version)) { |
- return false; |
- } |
- } else if (parameter_name.compare("ma") == 0) { |
+ if (parameter_name.compare("ma") == 0) { |
if (!ParsePositiveInteger32(parameter_value_begin, c, &max_age)) { |
return false; |
} |
@@ -154,10 +152,41 @@ bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
if (!ParseProbability(parameter_value_begin + 1, c - 1, &probability)) { |
return false; |
} |
+ } else if (parameter_name.compare("v") == 0) { |
+ // Version is a comma separated list of positive integers enclosed in |
+ // quotation marks. Since it can contain commas, which are not |
+ // delineating alternative service entries, |parameters_end| and |c| can |
+ // be invalid. |
+ if (*parameter_value_begin != '"') { |
+ return false; |
+ } |
+ c = std::find(parameter_value_begin + 1, value.end(), '"'); |
+ if (c == value.end()) { |
+ return false; |
+ } |
+ ++c; |
+ parameters_end = std::find(c, value.end(), ','); |
+ StringPiece::const_iterator v_begin = parameter_value_begin + 1; |
+ while (v_begin < c) { |
+ StringPiece::const_iterator v_end = v_begin; |
+ while (v_end < c - 1 && *v_end != ',') { |
+ ++v_end; |
+ } |
+ uint16 v; |
+ if (!ParsePositiveInteger16(v_begin, v_end, &v)) { |
+ return false; |
+ } |
+ version.push_back(v); |
+ v_begin = v_end + 1; |
+ if (v_begin == c - 1) { |
+ // List ends in comma. |
+ return false; |
+ } |
+ } |
} |
} |
altsvc_vector->push_back(AlternativeService(protocol_id, host, port, |
- version, max_age, probability)); |
+ max_age, probability, version)); |
for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { |
} |
} |
@@ -217,15 +246,23 @@ std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
value.push_back(c); |
} |
base::StringAppendF(&value, ":%d\"", altsvc.port); |
- if (altsvc.version != 0) { |
- base::StringAppendF(&value, "; v=%d", altsvc.version); |
- } |
if (altsvc.max_age != 86400) { |
base::StringAppendF(&value, "; ma=%d", altsvc.max_age); |
} |
if (altsvc.probability != 1.0) { |
base::StringAppendF(&value, "; p=\"%.2f\"", altsvc.probability); |
} |
+ if (!altsvc.version.empty()) { |
+ value.append("; v=\""); |
+ for (VersionVector::const_iterator it = altsvc.version.begin(); |
+ it != altsvc.version.end(); ++it) { |
+ if (it != altsvc.version.begin()) { |
+ value.append(","); |
+ } |
+ base::StringAppendF(&value, "%d", *it); |
+ } |
+ value.append("\""); |
+ } |
} |
return value; |
} |