summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_framer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_framer.cc')
-rw-r--r--net/spdy/spdy_framer.cc44
1 files changed, 37 insertions, 7 deletions
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index e001d86..2d9ea98 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -237,7 +237,7 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
// This is just a sanity check for help debugging early frame errors.
if (remaining_payload_ > 1000000u) {
- LOG(ERROR) <<
+ LOG(WARNING) <<
"Unexpectedly large frame. Spdy session is likely corrupt.";
}
@@ -293,10 +293,14 @@ void SpdyFramer::ProcessControlFrameHeader() {
// NOOP. Swallow it.
CHANGE_STATE(SPDY_AUTO_RESET);
return;
+ case GOAWAY:
+ if (current_control_frame.length() !=
+ SpdyGoAwayControlFrame::size() - SpdyFrame::size())
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ break;
default:
LOG(WARNING) << "Valid spdy control frame with unknown type: "
- << current_control_frame.type()
- << ". This should never happen";
+ << current_control_frame.type();
DCHECK(false);
set_error(SPDY_INVALID_CONTROL_FRAME);
break;
@@ -338,8 +342,11 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
// If this is a FIN, tell the caller.
if (control_frame.type() == SYN_REPLY &&
- control_frame.flags() & CONTROL_FLAG_FIN)
- visitor_->OnStreamFrameData(control_frame.stream_id(), NULL, 0);
+ control_frame.flags() & CONTROL_FLAG_FIN) {
+ visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
+ &control_frame)->stream_id(),
+ NULL, 0);
+ }
CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
} while (false);
@@ -518,6 +525,18 @@ SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id,
return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
}
+/* static */
+SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
+ SpdyStreamId last_accepted_stream_id) {
+ SpdyFrameBuilder frame;
+ frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
+ frame.WriteUInt16(GOAWAY);
+ size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size();
+ frame.WriteUInt32(go_away_size);
+ frame.WriteUInt32(last_accepted_stream_id);
+ return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
+}
+
SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id,
SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
@@ -582,7 +601,13 @@ SpdyControlFrame* SpdyFramer::CreateNopFrame() {
return reinterpret_cast<SpdyControlFrame*>(frame.take());
}
-static const int kCompressorLevel = Z_DEFAULT_COMPRESSION;
+// The following compression setting are based on Brian Olson's analysis. See
+// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
+// for more details.
+static const int kCompressorLevel = 9;
+static const int kCompressorWindowSizeInBits = 11;
+static const int kCompressorMemLevel = 1;
+
// This is just a hacked dictionary to use for shrinking HTTP-like headers.
// TODO(mbelshe): Use a scientific methodology for computing the dictionary.
const char SpdyFramer::kDictionary[] =
@@ -610,7 +635,12 @@ bool SpdyFramer::InitializeCompressor() {
compressor_.reset(new z_stream);
memset(compressor_.get(), 0, sizeof(z_stream));
- int success = deflateInit(compressor_.get(), kCompressorLevel);
+ int success = deflateInit2(compressor_.get(),
+ kCompressorLevel,
+ Z_DEFLATED,
+ kCompressorWindowSizeInBits,
+ kCompressorMemLevel,
+ Z_DEFAULT_STRATEGY);
if (success == Z_OK)
success = deflateSetDictionary(compressor_.get(),
reinterpret_cast<const Bytef*>(kDictionary),