#include "net/http/http_server_properties.h"
#include "net/http/http_util.h"
#include "net/http/transport_security_state.h"
+#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_buffer_producer.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_http_utils.h"
return dict;
}
+base::Value* NetLogSpdyInitializedCallback(NetLog::Source source,
+ const NextProto protocol_version,
+ NetLog::LogLevel /* log_level */) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ if (source.IsValid()) {
+ source.AddToEventParameters(dict);
+ }
+ dict->SetString("protocol",
+ SSLClientSocket::NextProtoToString(protocol_version));
+ return dict;
+}
+
base::Value* NetLogSpdySettingsCallback(const HostPortPair& host_port_pair,
bool clear_persisted,
NetLog::LogLevel /* log_level */) {
}
base::Value* NetLogSpdySettingCallback(SpdySettingsIds id,
+ const SpdyMajorVersion protocol_version,
SpdySettingsFlags flags,
uint32 value,
NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetInteger("id", id);
+ dict->SetInteger("id",
+ SpdyConstants::SerializeSettingId(protocol_version, id));
dict->SetInteger("flags", flags);
dict->SetInteger("value", value);
return dict;
}
-base::Value* NetLogSpdySendSettingsCallback(const SettingsMap* settings,
- NetLog::LogLevel /* log_level */) {
+base::Value* NetLogSpdySendSettingsCallback(
+ const SettingsMap* settings,
+ const SpdyMajorVersion protocol_version,
+ NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
base::ListValue* settings_list = new base::ListValue();
for (SettingsMap::const_iterator it = settings->begin();
const SpdySettingsIds id = it->first;
const SpdySettingsFlags flags = it->second.first;
const uint32 value = it->second.second;
- settings_list->Append(new base::StringValue(
- base::StringPrintf("[id:%u flags:%u value:%u]", id, flags, value)));
+ settings_list->Append(new base::StringValue(base::StringPrintf(
+ "[id:%u flags:%u value:%u]",
+ SpdyConstants::SerializeSettingId(protocol_version, id),
+ flags,
+ value)));
}
dict->Set("settings", settings_list);
return dict;
std::string pinning_failure_log;
if (!transport_security_state->CheckPublicKeyPins(
new_hostname,
- true, /* sni_available */
ssl_info.is_issued_by_known_root,
ssl_info.public_key_hashes,
&pinning_failure_log)) {
transport_security_state_(transport_security_state),
read_buffer_(new IOBuffer(kReadBufferSize)),
stream_hi_water_mark_(kFirstStreamId),
+ last_accepted_push_stream_id_(0),
num_pushed_streams_(0u),
num_active_pushed_streams_(0u),
in_flight_write_frame_type_(DATA),
enable_compression_));
buffered_spdy_framer_->set_visitor(this);
buffered_spdy_framer_->set_debug_visitor(this);
- UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol_, kProtoMaximumVersion);
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- UMA_HISTOGRAM_BOOLEAN("Net.SpdySessions_DataReductionProxy",
- host_port_pair().Equals(HostPortPair::FromURL(
- GURL(SPDY_PROXY_AUTH_ORIGIN))));
-#endif
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.SpdyVersion2",
+ protocol_ - kProtoSPDYMinimumVersion,
+ kProtoSPDYMaximumVersion - kProtoSPDYMinimumVersion + 1);
- net_log_.AddEvent(
- NetLog::TYPE_SPDY_SESSION_INITIALIZED,
- connection_->socket()->NetLog().source().ToEventParametersCallback());
+ net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_INITIALIZED,
+ base::Bind(&NetLogSpdyInitializedCallback,
+ connection_->socket()->NetLog().source(),
+ protocol_));
DCHECK_EQ(availability_state_, STATE_AVAILABLE);
connection_->AddHigherLayeredPool(this);
scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass()));
- if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
+ // Send window size is based on payload size, so nothing to do if this is
+ // just a FIN with no payload.
+ if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION &&
+ effective_len != 0) {
DecreaseSendWindowSize(static_cast<int32>(effective_len));
data_buffer->AddConsumeCallback(
base::Bind(&SpdySession::OnWriteBufferConsumed,
err != ERR_SOCKET_NOT_CONNECTED &&
err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) {
// Enqueue a GOAWAY to inform the peer of why we're closing the connection.
- SpdyGoAwayIR goaway_ir(0, // Last accepted stream ID.
+ SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_,
MapNetErrorToGoAwayStatus(err),
description);
EnqueueSessionWrite(HIGHEST,
received_settings_ = true;
// Log the setting.
- net_log_.AddEvent(
- NetLog::TYPE_SPDY_SESSION_RECV_SETTING,
- base::Bind(&NetLogSpdySettingCallback,
- id, static_cast<SpdySettingsFlags>(flags), value));
+ const SpdyMajorVersion protocol_version = GetProtocolVersion();
+ net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_RECV_SETTING,
+ base::Bind(&NetLogSpdySettingCallback,
+ id,
+ protocol_version,
+ static_cast<SpdySettingsFlags>(flags),
+ value));
}
void SpdySession::OnSendCompressedFrame(
}
}
+bool SpdySession::OnUnknownFrame(SpdyStreamId stream_id, int frame_type) {
+ // Validate stream id.
+ // Was the frame sent on a stream id that has not been used in this session?
+ if (stream_id % 2 == 1 && stream_id > stream_hi_water_mark_)
+ return false;
+
+ if (stream_id % 2 == 0 && stream_id > last_accepted_push_stream_id_)
+ return false;
+
+ return true;
+}
+
void SpdySession::OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) {
CHECK(in_io_loop_);
// Server-initiated streams should have even sequence numbers.
if ((stream_id & 0x1) != 0) {
LOG(WARNING) << "Received invalid push stream id " << stream_id;
+ if (GetProtocolVersion() > SPDY2)
+ CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Odd push stream id.");
return false;
}
+ if (GetProtocolVersion() > SPDY2) {
+ if (stream_id <= last_accepted_push_stream_id_) {
+ LOG(WARNING) << "Received push stream id lesser or equal to the last "
+ << "accepted before " << stream_id;
+ CloseSessionOnError(
+ ERR_SPDY_PROTOCOL_ERROR,
+ "New push stream id must be greater than the last accepted.");
+ return false;
+ }
+ }
+
if (IsStreamActive(stream_id)) {
+ // For SPDY3 and higher we should not get here, we'll start going away
+ // earlier on |last_seen_push_stream_id_| check.
+ CHECK_GT(SPDY3, GetProtocolVersion());
LOG(WARNING) << "Received push for active stream " << stream_id;
return false;
}
+ last_accepted_push_stream_id_ = stream_id;
+
RequestPriority request_priority =
ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion());
kDefaultInitialRecvWindowSize - session_recv_window_size_);
}
- // Finally, notify the server about the settings they have
- // previously told us to use when communicating with them (after
- // applying them).
- const SettingsMap& server_settings_map =
- http_server_properties_->GetSpdySettings(host_port_pair());
- if (server_settings_map.empty())
- return;
+ if (protocol_ <= kProtoSPDY31) {
+ // Finally, notify the server about the settings they have
+ // previously told us to use when communicating with them (after
+ // applying them).
+ const SettingsMap& server_settings_map =
+ http_server_properties_->GetSpdySettings(host_port_pair());
+ if (server_settings_map.empty())
+ return;
- SettingsMap::const_iterator it =
- server_settings_map.find(SETTINGS_CURRENT_CWND);
- uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0;
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100);
+ SettingsMap::const_iterator it =
+ server_settings_map.find(SETTINGS_CURRENT_CWND);
+ uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0;
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100);
- for (SettingsMap::const_iterator it = server_settings_map.begin();
- it != server_settings_map.end(); ++it) {
- const SpdySettingsIds new_id = it->first;
- const uint32 new_val = it->second.second;
- HandleSetting(new_id, new_val);
- }
+ for (SettingsMap::const_iterator it = server_settings_map.begin();
+ it != server_settings_map.end(); ++it) {
+ const SpdySettingsIds new_id = it->first;
+ const uint32 new_val = it->second.second;
+ HandleSetting(new_id, new_val);
+ }
- SendSettings(server_settings_map);
+ SendSettings(server_settings_map);
+ }
}
void SpdySession::SendSettings(const SettingsMap& settings) {
+ const SpdyMajorVersion protocol_version = GetProtocolVersion();
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
- base::Bind(&NetLogSpdySendSettingsCallback, &settings));
-
+ base::Bind(&NetLogSpdySendSettingsCallback, &settings, protocol_version));
// Create the SETTINGS frame and send it.
DCHECK(buffered_spdy_framer_.get());
scoped_ptr<SpdyFrame> settings_frame(