Home | History | Annotate | Download | only in spdy
      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/spdy/buffered_spdy_framer.h"
      6 
      7 #include "base/logging.h"
      8 
      9 namespace net {
     10 
     11 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
     12   switch (next_proto) {
     13     case kProtoSPDY2:
     14     case kProtoSPDY21:
     15       return SPDY2;
     16     case kProtoSPDY3:
     17     case kProtoSPDY31:
     18       return SPDY3;
     19     // SPDY/4 and HTTP/2 share the same framing for now.
     20     case kProtoSPDY4a2:
     21     case kProtoHTTP2Draft04:
     22       return SPDY4;
     23     case kProtoUnknown:
     24     case kProtoHTTP11:
     25     case kProtoSPDY1:
     26     case kProtoQUIC1SPDY3:
     27       break;
     28   }
     29   NOTREACHED();
     30   return SPDY2;
     31 }
     32 
     33 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
     34                                        bool enable_compression)
     35     : spdy_framer_(version),
     36       visitor_(NULL),
     37       header_buffer_used_(0),
     38       header_buffer_valid_(false),
     39       header_stream_id_(SpdyFramer::kInvalidStream),
     40       frames_received_(0) {
     41   spdy_framer_.set_enable_compression(enable_compression);
     42   memset(header_buffer_, 0, sizeof(header_buffer_));
     43 }
     44 
     45 BufferedSpdyFramer::~BufferedSpdyFramer() {
     46 }
     47 
     48 void BufferedSpdyFramer::set_visitor(
     49     BufferedSpdyFramerVisitorInterface* visitor) {
     50   visitor_ = visitor;
     51   spdy_framer_.set_visitor(this);
     52 }
     53 
     54 void BufferedSpdyFramer::set_debug_visitor(
     55     SpdyFramerDebugVisitorInterface* debug_visitor) {
     56   spdy_framer_.set_debug_visitor(debug_visitor);
     57 }
     58 
     59 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
     60   DCHECK(spdy_framer);
     61   visitor_->OnError(spdy_framer->error_code());
     62 }
     63 
     64 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
     65                                      SpdyStreamId associated_stream_id,
     66                                      SpdyPriority priority,
     67                                      uint8 credential_slot,
     68                                      bool fin,
     69                                      bool unidirectional) {
     70   frames_received_++;
     71   DCHECK(!control_frame_fields_.get());
     72   control_frame_fields_.reset(new ControlFrameFields());
     73   control_frame_fields_->type = SYN_STREAM;
     74   control_frame_fields_->stream_id = stream_id;
     75   control_frame_fields_->associated_stream_id = associated_stream_id;
     76   control_frame_fields_->priority = priority;
     77   control_frame_fields_->credential_slot = credential_slot;
     78   control_frame_fields_->fin = fin;
     79   control_frame_fields_->unidirectional = unidirectional;
     80 
     81   InitHeaderStreaming(stream_id);
     82 }
     83 
     84 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
     85                                    bool fin) {
     86   frames_received_++;
     87   DCHECK(!control_frame_fields_.get());
     88   control_frame_fields_.reset(new ControlFrameFields());
     89   control_frame_fields_->type = HEADERS;
     90   control_frame_fields_->stream_id = stream_id;
     91   control_frame_fields_->fin = fin;
     92 
     93   InitHeaderStreaming(stream_id);
     94 }
     95 
     96 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
     97                                     bool fin) {
     98   frames_received_++;
     99   DCHECK(!control_frame_fields_.get());
    100   control_frame_fields_.reset(new ControlFrameFields());
    101   control_frame_fields_->type = SYN_REPLY;
    102   control_frame_fields_->stream_id = stream_id;
    103   control_frame_fields_->fin = fin;
    104 
    105   InitHeaderStreaming(stream_id);
    106 }
    107 
    108 bool BufferedSpdyFramer::OnCredentialFrameData(const char* frame_data,
    109                                                size_t len) {
    110   DCHECK(false);
    111   return false;
    112 }
    113 
    114 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id,
    115                                                   const char* header_data,
    116                                                   size_t len) {
    117   CHECK_EQ(header_stream_id_, stream_id);
    118 
    119   if (len == 0) {
    120     // Indicates end-of-header-block.
    121     CHECK(header_buffer_valid_);
    122 
    123     SpdyHeaderBlock headers;
    124     size_t parsed_len = spdy_framer_.ParseHeaderBlockInBuffer(
    125         header_buffer_, header_buffer_used_, &headers);
    126     // TODO(rch): this really should be checking parsed_len != len,
    127     // but a bunch of tests fail.  Need to figure out why.
    128     if (parsed_len == 0) {
    129       visitor_->OnStreamError(
    130           stream_id, "Could not parse Spdy Control Frame Header.");
    131       return false;
    132     }
    133     DCHECK(control_frame_fields_.get());
    134     switch (control_frame_fields_->type) {
    135       case SYN_STREAM:
    136         visitor_->OnSynStream(control_frame_fields_->stream_id,
    137                               control_frame_fields_->associated_stream_id,
    138                               control_frame_fields_->priority,
    139                               control_frame_fields_->credential_slot,
    140                               control_frame_fields_->fin,
    141                               control_frame_fields_->unidirectional,
    142                               headers);
    143         break;
    144       case SYN_REPLY:
    145         visitor_->OnSynReply(control_frame_fields_->stream_id,
    146                              control_frame_fields_->fin,
    147                              headers);
    148         break;
    149       case HEADERS:
    150         visitor_->OnHeaders(control_frame_fields_->stream_id,
    151                             control_frame_fields_->fin,
    152                             headers);
    153         break;
    154       default:
    155         DCHECK(false) << "Unexpect control frame type: "
    156                       << control_frame_fields_->type;
    157         break;
    158     }
    159     control_frame_fields_.reset(NULL);
    160     return true;
    161   }
    162 
    163   const size_t available = kHeaderBufferSize - header_buffer_used_;
    164   if (len > available) {
    165     header_buffer_valid_ = false;
    166     visitor_->OnStreamError(
    167         stream_id, "Received more data than the allocated size.");
    168     return false;
    169   }
    170   memcpy(header_buffer_ + header_buffer_used_, header_data, len);
    171   header_buffer_used_ += len;
    172   return true;
    173 }
    174 
    175 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
    176                                            size_t length,
    177                                            bool fin) {
    178   frames_received_++;
    179   header_stream_id_ = stream_id;
    180 }
    181 
    182 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
    183                                            const char* data,
    184                                            size_t len,
    185                                            bool fin) {
    186   visitor_->OnStreamFrameData(stream_id, data, len, fin);
    187 }
    188 
    189 void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
    190   visitor_->OnSettings(clear_persisted);
    191 }
    192 
    193 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
    194                                    uint8 flags,
    195                                    uint32 value) {
    196   visitor_->OnSetting(id, flags, value);
    197 }
    198 
    199 void BufferedSpdyFramer::OnPing(uint32 unique_id) {
    200   visitor_->OnPing(unique_id);
    201 }
    202 
    203 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id,
    204                                      SpdyRstStreamStatus status) {
    205   visitor_->OnRstStream(stream_id, status);
    206 }
    207 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id,
    208                                   SpdyGoAwayStatus status) {
    209   visitor_->OnGoAway(last_accepted_stream_id, status);
    210 }
    211 
    212 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id,
    213                                         uint32 delta_window_size) {
    214   visitor_->OnWindowUpdate(stream_id, delta_window_size);
    215 }
    216 
    217 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
    218                                        SpdyStreamId promised_stream_id) {
    219   visitor_->OnPushPromise(stream_id, promised_stream_id);
    220 }
    221 
    222 int BufferedSpdyFramer::protocol_version() {
    223   return spdy_framer_.protocol_version();
    224 }
    225 
    226 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) {
    227   return spdy_framer_.ProcessInput(data, len);
    228 }
    229 
    230 void BufferedSpdyFramer::Reset() {
    231   spdy_framer_.Reset();
    232 }
    233 
    234 SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const {
    235   return spdy_framer_.error_code();
    236 }
    237 
    238 SpdyFramer::SpdyState BufferedSpdyFramer::state() const {
    239   return spdy_framer_.state();
    240 }
    241 
    242 bool BufferedSpdyFramer::MessageFullyRead() {
    243   return state() == SpdyFramer::SPDY_AUTO_RESET;
    244 }
    245 
    246 bool BufferedSpdyFramer::HasError() {
    247   return spdy_framer_.HasError();
    248 }
    249 
    250 SpdyFrame* BufferedSpdyFramer::CreateSynStream(
    251     SpdyStreamId stream_id,
    252     SpdyStreamId associated_stream_id,
    253     SpdyPriority priority,
    254     uint8 credential_slot,
    255     SpdyControlFlags flags,
    256     bool compressed,
    257     const SpdyHeaderBlock* headers) {
    258   return spdy_framer_.CreateSynStream(stream_id, associated_stream_id, priority,
    259                                       credential_slot, flags, compressed,
    260                                       headers);
    261 }
    262 
    263 SpdyFrame* BufferedSpdyFramer::CreateSynReply(
    264     SpdyStreamId stream_id,
    265     SpdyControlFlags flags,
    266     bool compressed,
    267     const SpdyHeaderBlock* headers) {
    268   return spdy_framer_.CreateSynReply(stream_id, flags, compressed, headers);
    269 }
    270 
    271 SpdyFrame* BufferedSpdyFramer::CreateRstStream(
    272     SpdyStreamId stream_id,
    273     SpdyRstStreamStatus status) const {
    274   return spdy_framer_.CreateRstStream(stream_id, status);
    275 }
    276 
    277 SpdyFrame* BufferedSpdyFramer::CreateSettings(
    278     const SettingsMap& values) const {
    279   return spdy_framer_.CreateSettings(values);
    280 }
    281 
    282 SpdyFrame* BufferedSpdyFramer::CreatePingFrame(
    283     uint32 unique_id) const {
    284   return spdy_framer_.CreatePingFrame(unique_id);
    285 }
    286 
    287 SpdyFrame* BufferedSpdyFramer::CreateGoAway(
    288     SpdyStreamId last_accepted_stream_id,
    289     SpdyGoAwayStatus status) const {
    290   return spdy_framer_.CreateGoAway(last_accepted_stream_id, status);
    291 }
    292 
    293 SpdyFrame* BufferedSpdyFramer::CreateHeaders(
    294     SpdyStreamId stream_id,
    295     SpdyControlFlags flags,
    296     bool compressed,
    297     const SpdyHeaderBlock* headers) {
    298   return spdy_framer_.CreateHeaders(stream_id, flags, compressed, headers);
    299 }
    300 
    301 SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
    302     SpdyStreamId stream_id,
    303     uint32 delta_window_size) const {
    304   return spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size);
    305 }
    306 
    307 SpdyFrame* BufferedSpdyFramer::CreateCredentialFrame(
    308     const SpdyCredential& credential) const {
    309   return spdy_framer_.CreateCredentialFrame(credential);
    310 }
    311 
    312 SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
    313                                                const char* data,
    314                                                uint32 len,
    315                                                SpdyDataFlags flags) {
    316   return spdy_framer_.CreateDataFrame(stream_id, data, len, flags);
    317 }
    318 
    319 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
    320   return spdy_framer_.GetHighestPriority();
    321 }
    322 
    323 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
    324   memset(header_buffer_, 0, kHeaderBufferSize);
    325   header_buffer_used_ = 0;
    326   header_buffer_valid_ = true;
    327   header_stream_id_ = stream_id;
    328   DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
    329 }
    330 
    331 }  // namespace net
    332