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 <limits>
      6 
      7 #include "base/sys_byteorder.h"
      8 #include "net/spdy/spdy_frame_reader.h"
      9 #include "net/spdy/spdy_protocol.h"
     10 
     11 namespace net {
     12 
     13 SpdyFrameReader::SpdyFrameReader(const char* data, const size_t len)
     14     : data_(data),
     15       len_(len),
     16       ofs_(0) {
     17 }
     18 
     19 bool SpdyFrameReader::ReadUInt8(uint8* result) {
     20   // Make sure that we have the whole uint8.
     21   if (!CanRead(1)) {
     22     OnFailure();
     23     return false;
     24   }
     25 
     26   // Read into result.
     27   *result = *reinterpret_cast<const uint8*>(data_ + ofs_);
     28 
     29   // Iterate.
     30   ofs_ += 1;
     31 
     32   return true;
     33 }
     34 
     35 bool SpdyFrameReader::ReadUInt16(uint16* result) {
     36   // Make sure that we have the whole uint16.
     37   if (!CanRead(2)) {
     38     OnFailure();
     39     return false;
     40   }
     41 
     42   // Read into result.
     43   *result = ntohs(*(reinterpret_cast<const uint16*>(data_ + ofs_)));
     44 
     45   // Iterate.
     46   ofs_ += 2;
     47 
     48   return true;
     49 }
     50 
     51 bool SpdyFrameReader::ReadUInt32(uint32* result) {
     52   // Make sure that we have the whole uint32.
     53   if (!CanRead(4)) {
     54     OnFailure();
     55     return false;
     56   }
     57 
     58   // Read into result.
     59   *result = ntohl(*(reinterpret_cast<const uint32*>(data_ + ofs_)));
     60 
     61   // Iterate.
     62   ofs_ += 4;
     63 
     64   return true;
     65 }
     66 
     67 bool SpdyFrameReader::ReadUInt64(uint64* result) {
     68   // Make sure that we have the whole uint64.
     69   if (!CanRead(8)) {
     70     OnFailure();
     71     return false;
     72   }
     73 
     74   // Read into result. Network byte order is big-endian.
     75   uint64 upper = ntohl(*(reinterpret_cast<const uint32*>(data_ + ofs_)));
     76   uint64 lower = ntohl(*(reinterpret_cast<const uint32*>(data_ + ofs_ + 4)));
     77   *result = (upper << 32) + lower;
     78 
     79   // Iterate.
     80   ofs_ += 8;
     81 
     82   return true;
     83 }
     84 
     85 bool SpdyFrameReader::ReadUInt31(uint32* result) {
     86   bool success = ReadUInt32(result);
     87 
     88   // Zero out highest-order bit.
     89   if (success) {
     90     *result &= 0x7fffffff;
     91   }
     92 
     93   return success;
     94 }
     95 
     96 bool SpdyFrameReader::ReadUInt24(uint32* result) {
     97   // Make sure that we have the whole uint24.
     98   if (!CanRead(3)) {
     99     OnFailure();
    100     return false;
    101   }
    102 
    103   // Read into result.
    104   *result = 0;
    105   memcpy(reinterpret_cast<char*>(result) + 1, data_ + ofs_, 3);
    106   *result = ntohl(*result);
    107 
    108   // Iterate.
    109   ofs_ += 3;
    110 
    111   return true;
    112 }
    113 
    114 bool SpdyFrameReader::ReadStringPiece16(base::StringPiece* result) {
    115   // Read resultant length.
    116   uint16 result_len;
    117   if (!ReadUInt16(&result_len)) {
    118     // OnFailure() already called.
    119     return false;
    120   }
    121 
    122   // Make sure that we have the whole string.
    123   if (!CanRead(result_len)) {
    124     OnFailure();
    125     return false;
    126   }
    127 
    128   // Set result.
    129   result->set(data_ + ofs_, result_len);
    130 
    131   // Iterate.
    132   ofs_ += result_len;
    133 
    134   return true;
    135 }
    136 
    137 bool SpdyFrameReader::ReadStringPiece32(base::StringPiece* result) {
    138   // Read resultant length.
    139   uint32 result_len;
    140   if (!ReadUInt32(&result_len)) {
    141     // OnFailure() already called.
    142     return false;
    143   }
    144 
    145   // Make sure that we have the whole string.
    146   if (!CanRead(result_len)) {
    147     OnFailure();
    148     return false;
    149   }
    150 
    151   // Set result.
    152   result->set(data_ + ofs_, result_len);
    153 
    154   // Iterate.
    155   ofs_ += result_len;
    156 
    157   return true;
    158 }
    159 
    160 bool SpdyFrameReader::ReadBytes(void* result, size_t size) {
    161   // Make sure that we have enough data to read.
    162   if (!CanRead(size)) {
    163     OnFailure();
    164     return false;
    165   }
    166 
    167   // Read into result.
    168   memcpy(result, data_ + ofs_, size);
    169 
    170   // Iterate.
    171   ofs_ += size;
    172 
    173   return true;
    174 }
    175 
    176 bool SpdyFrameReader::Seek(size_t size) {
    177   if (!CanRead(size)) {
    178     OnFailure();
    179     return false;
    180   }
    181 
    182   // Iterate.
    183   ofs_ += size;
    184 
    185   return true;
    186 }
    187 
    188 bool SpdyFrameReader::IsDoneReading() const {
    189   return len_ == ofs_;
    190 }
    191 
    192 bool SpdyFrameReader::CanRead(size_t bytes) const {
    193   return bytes <= (len_ - ofs_);
    194 }
    195 
    196 void SpdyFrameReader::OnFailure() {
    197   // Set our iterator to the end of the buffer so that further reads fail
    198   // immediately.
    199   ofs_ = len_;
    200 }
    201 
    202 }  // namespace net
    203