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