OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/core/spdy_frame_builder.h" | 5 #include "net/spdy/core/spdy_frame_builder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstdint> | 8 #include <cstdint> |
9 #include <limits> | 9 #include <limits> |
10 #include <new> | 10 #include <new> |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 | 65 |
66 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, | 66 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, |
67 SpdyFrameType type, | 67 SpdyFrameType type, |
68 uint8_t flags, | 68 uint8_t flags, |
69 SpdyStreamId stream_id) { | 69 SpdyStreamId stream_id) { |
70 uint8_t raw_frame_type = SerializeFrameType(type); | 70 uint8_t raw_frame_type = SerializeFrameType(type); |
71 DCHECK(IsDefinedFrameType(raw_frame_type)); | 71 DCHECK(IsDefinedFrameType(raw_frame_type)); |
72 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 72 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
73 bool success = true; | 73 bool success = true; |
74 if (length_ > 0) { | 74 if (length_ > 0) { |
75 // Update length field for previous frame. | 75 SPDY_BUG << "SpdyFrameBuilder doesn't have a clean state when BeginNewFrame" |
76 OverwriteLength(framer, length_ - kFrameHeaderSize); | 76 << "is called. Leftover length_ is " << length_; |
77 SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_) | 77 offset_ += length_; |
78 << "Frame length " << length_ | 78 length_ = 0; |
79 << " is longer than the maximum allowed length."; | |
80 } | 79 } |
81 | 80 |
82 offset_ += length_; | 81 success &= WriteUInt24(capacity_ - offset_ - kFrameHeaderSize); |
83 length_ = 0; | |
84 | |
85 // TODO(yasong): remove after OverwriteLength() is deleted. | |
86 bool length_written = false; | |
87 // Remember where the length field is written. Used for OverwriteLength(). | |
88 if (output_ != nullptr && CanWrite(kLengthFieldLength)) { | |
89 // Can write the length field. | |
90 char* dest = nullptr; | |
91 // |size| is the available bytes in the current memory block. | |
92 int size = 0; | |
93 output_->Next(&dest, &size); | |
94 start_of_current_frame_ = dest; | |
95 bytes_of_length_written_in_first_block_ = | |
96 size > (int)kLengthFieldLength ? kLengthFieldLength : size; | |
97 // If the current block is not enough for the length field, write the | |
98 // length field here, and remember the pointer to the next block. | |
99 if (size < (int)kLengthFieldLength) { | |
100 // Write the first portion of the length field. | |
101 int value = base::HostToNet32(capacity_ - offset_ - kFrameHeaderSize); | |
102 memcpy(dest, reinterpret_cast<char*>(&value) + 1, size); | |
103 Seek(size); | |
104 output_->Next(&dest, &size); | |
105 start_of_current_frame_in_next_block_ = dest; | |
106 int size_left = | |
107 kLengthFieldLength - bytes_of_length_written_in_first_block_; | |
108 memcpy(dest, reinterpret_cast<char*>(&value) + 1 + size, size_left); | |
109 Seek(size_left); | |
110 length_written = true; | |
111 } | |
112 } | |
113 | |
114 // Assume all remaining capacity will be used for this frame. If not, | |
115 // the length will get overwritten when we begin the next frame. | |
116 // Don't check for length limits here because this may be larger than the | |
117 // actual frame length. | |
118 if (!length_written) { | |
119 success &= WriteUInt24(capacity_ - offset_ - kFrameHeaderSize); | |
120 } | |
121 success &= WriteUInt8(raw_frame_type); | 82 success &= WriteUInt8(raw_frame_type); |
122 success &= WriteUInt8(flags); | 83 success &= WriteUInt8(flags); |
123 success &= WriteUInt32(stream_id); | 84 success &= WriteUInt32(stream_id); |
124 DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_); | 85 DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_); |
125 return success; | 86 return success; |
126 } | 87 } |
127 | 88 |
128 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, | 89 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, |
129 SpdyFrameType type, | 90 SpdyFrameType type, |
130 uint8_t flags, | 91 uint8_t flags, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 const char* src = data_ptr + total_written; | 174 const char* src = data_ptr + total_written; |
214 memcpy(dest, src, to_copy); | 175 memcpy(dest, src, to_copy); |
215 Seek(to_copy); | 176 Seek(to_copy); |
216 data_len -= to_copy; | 177 data_len -= to_copy; |
217 total_written += to_copy; | 178 total_written += to_copy; |
218 } | 179 } |
219 } | 180 } |
220 return true; | 181 return true; |
221 } | 182 } |
222 | 183 |
223 bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer, | |
224 size_t length) { | |
225 if (output_ != nullptr) { | |
226 size_t value = base::HostToNet32(length); | |
227 if (start_of_current_frame_ != nullptr && | |
228 bytes_of_length_written_in_first_block_ == kLengthFieldLength) { | |
229 // Length field of the current frame is within one memory block. | |
230 memcpy(start_of_current_frame_, reinterpret_cast<char*>(&value) + 1, | |
231 kLengthFieldLength); | |
232 return true; | |
233 } else if (start_of_current_frame_ != nullptr && | |
234 start_of_current_frame_in_next_block_ != nullptr && | |
235 bytes_of_length_written_in_first_block_ < kLengthFieldLength) { | |
236 // Length field of the current frame crosses two memory blocks. | |
237 memcpy(start_of_current_frame_, reinterpret_cast<char*>(&value) + 1, | |
238 bytes_of_length_written_in_first_block_); | |
239 memcpy(start_of_current_frame_in_next_block_, | |
240 reinterpret_cast<char*>(&value) + 1 + | |
241 bytes_of_length_written_in_first_block_, | |
242 kLengthFieldLength - bytes_of_length_written_in_first_block_); | |
243 return true; | |
244 } else { | |
245 return false; | |
246 } | |
247 } | |
248 | |
249 DCHECK_GE(framer.GetFrameMaximumSize(), length); | |
250 bool success = false; | |
251 const size_t old_length = length_; | |
252 | |
253 length_ = 0; | |
254 success = WriteUInt24(length); | |
255 | |
256 length_ = old_length; | |
257 return success; | |
258 } | |
259 | |
260 bool SpdyFrameBuilder::CanWrite(size_t length) const { | 184 bool SpdyFrameBuilder::CanWrite(size_t length) const { |
261 if (length > kLengthMask) { | 185 if (length > kLengthMask) { |
262 DCHECK(false); | 186 DCHECK(false); |
263 return false; | 187 return false; |
264 } | 188 } |
265 | 189 |
266 if (output_ == nullptr) { | 190 if (output_ == nullptr) { |
267 if (offset_ + length_ + length > capacity_) { | 191 if (offset_ + length_ + length > capacity_) { |
268 DLOG(FATAL) << "Requested: " << length << " capacity: " << capacity_ | 192 DLOG(FATAL) << "Requested: " << length << " capacity: " << capacity_ |
269 << " used: " << offset_ + length_; | 193 << " used: " << offset_ + length_; |
270 return false; | 194 return false; |
271 } | 195 } |
272 } else { | 196 } else { |
273 if (length > output_->BytesFree()) { | 197 if (length > output_->BytesFree()) { |
274 return false; | 198 return false; |
275 } | 199 } |
276 } | 200 } |
277 | 201 |
278 return true; | 202 return true; |
279 } | 203 } |
280 | 204 |
281 } // namespace net | 205 } // namespace net |
OLD | NEW |