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