• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SpdyFrameReader(const char * data,const size_t len)13 SpdyFrameReader::SpdyFrameReader(const char* data, const size_t len)
14     : data_(data),
15       len_(len),
16       ofs_(0) {
17 }
18 
ReadUInt8(uint8 * result)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 
ReadUInt16(uint16 * result)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 
ReadUInt32(uint32 * result)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 
ReadUInt64(uint64 * result)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 
ReadUInt31(uint32 * result)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 
ReadUInt24(uint32 * result)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 
ReadStringPiece16(base::StringPiece * result)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 
ReadStringPiece32(base::StringPiece * result)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 
ReadBytes(void * result,size_t size)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 
Seek(size_t size)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 
IsDoneReading() const188 bool SpdyFrameReader::IsDoneReading() const {
189   return len_ == ofs_;
190 }
191 
CanRead(size_t bytes) const192 bool SpdyFrameReader::CanRead(size_t bytes) const {
193   return bytes <= (len_ - ofs_);
194 }
195 
OnFailure()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