Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: net/spdy/spdy_frame_builder.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_frame_builder.h ('k') | net/spdy/spdy_frame_builder_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/spdy_frame_builder.h"
6
7 #include <algorithm>
8 #include <cstdint>
9 #include <limits>
10
11 #include "base/logging.h"
12 #include "net/spdy/spdy_bug_tracker.h"
13 #include "net/spdy/spdy_framer.h"
14 #include "net/spdy/spdy_protocol.h"
15 #include "net/spdy/zero_copy_output_buffer.h"
16
17 namespace net {
18
19 SpdyFrameBuilder::SpdyFrameBuilder(size_t size)
20 : buffer_(new char[size]), capacity_(size), length_(0), offset_(0) {}
21
22 SpdyFrameBuilder::SpdyFrameBuilder(size_t size, ZeroCopyOutputBuffer* output)
23 : buffer_(output == nullptr ? new char[size] : nullptr),
24 output_(output),
25 capacity_(size),
26 length_(0),
27 offset_(0) {}
28
29 SpdyFrameBuilder::~SpdyFrameBuilder() {
30 }
31
32 char* SpdyFrameBuilder::GetWritableBuffer(size_t length) {
33 if (!CanWrite(length)) {
34 return nullptr;
35 }
36 return buffer_.get() + offset_ + length_;
37 }
38
39 char* SpdyFrameBuilder::GetWritableOutput(size_t length,
40 size_t* actual_length) {
41 char* dest = nullptr;
42 int size = 0;
43
44 if (!CanWrite(length)) {
45 return nullptr;
46 }
47 output_->Next(&dest, &size);
48 *actual_length = std::min(length, (size_t)size);
49 return dest;
50 }
51
52 bool SpdyFrameBuilder::Seek(size_t length) {
53 if (!CanWrite(length)) {
54 return false;
55 }
56 if (output_ == nullptr) {
57 length_ += length;
58 } else {
59 output_->AdvanceWritePtr(length);
60 length_ += length;
61 }
62 return true;
63 }
64
65 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
66 SpdyFrameType type,
67 uint8_t flags,
68 SpdyStreamId stream_id) {
69 uint8_t raw_frame_type = SerializeFrameType(type);
70 DCHECK(IsDefinedFrameType(raw_frame_type));
71 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
72 bool success = true;
73 if (length_ > 0) {
74 // Update length field for previous frame.
75 OverwriteLength(framer, length_ - kFrameHeaderSize);
76 SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_)
77 << "Frame length " << length_
78 << " is longer than the maximum allowed length.";
79 }
80
81 offset_ += length_;
82 length_ = 0;
83
84 // TODO(yasong): remove after OverwriteLength() is deleted.
85 bool length_written = false;
86 // Remember where the length field is written. Used for OverwriteLength().
87 if (output_ != nullptr && CanWrite(kLengthFieldLength)) {
88 // Can write the length field.
89 char* dest = nullptr;
90 // |size| is the available bytes in the current memory block.
91 int size = 0;
92 output_->Next(&dest, &size);
93 start_of_current_frame_ = dest;
94 bytes_of_length_written_in_first_block_ =
95 size > (int)kLengthFieldLength ? kLengthFieldLength : size;
96 // If the current block is not enough for the length field, write the
97 // length field here, and remember the pointer to the next block.
98 if (size < (int)kLengthFieldLength) {
99 // Write the first portion of the length field.
100 int value = base::HostToNet32(capacity_ - offset_ - kFrameHeaderSize);
101 memcpy(dest, reinterpret_cast<char*>(&value) + 1, size);
102 Seek(size);
103 output_->Next(&dest, &size);
104 start_of_current_frame_in_next_block_ = dest;
105 int size_left =
106 kLengthFieldLength - bytes_of_length_written_in_first_block_;
107 memcpy(dest, reinterpret_cast<char*>(&value) + 1 + size, size_left);
108 Seek(size_left);
109 length_written = true;
110 }
111 }
112
113 // Assume all remaining capacity will be used for this frame. If not,
114 // the length will get overwritten when we begin the next frame.
115 // Don't check for length limits here because this may be larger than the
116 // actual frame length.
117 if (!length_written) {
118 success &= WriteUInt24(capacity_ - offset_ - kFrameHeaderSize);
119 }
120 success &= WriteUInt8(raw_frame_type);
121 success &= WriteUInt8(flags);
122 success &= WriteUInt32(stream_id);
123 DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
124 return success;
125 }
126
127 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
128 SpdyFrameType type,
129 uint8_t flags,
130 SpdyStreamId stream_id,
131 size_t length) {
132 uint8_t raw_frame_type = SerializeFrameType(type);
133 DCHECK(IsDefinedFrameType(raw_frame_type));
134 return BeginNewFrameInternal(framer, raw_frame_type, flags, stream_id,
135 length);
136 }
137
138 bool SpdyFrameBuilder::BeginNewExtensionFrame(const SpdyFramer& framer,
139 uint8_t raw_frame_type,
140 uint8_t flags,
141 SpdyStreamId stream_id,
142 size_t length) {
143 DCHECK(!IsDefinedFrameType(raw_frame_type));
144 return BeginNewFrameInternal(framer, raw_frame_type, flags, stream_id,
145 length);
146 }
147
148 bool SpdyFrameBuilder::BeginNewFrameInternal(const SpdyFramer& framer,
149 uint8_t raw_frame_type,
150 uint8_t flags,
151 SpdyStreamId stream_id,
152 size_t length) {
153 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
154 bool success = true;
155 SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_)
156 << "Frame length " << length_
157 << " is longer than the maximum allowed length.";
158
159 offset_ += length_;
160 length_ = 0;
161
162 success &= WriteUInt24(length);
163 success &= WriteUInt8(raw_frame_type);
164 success &= WriteUInt8(flags);
165 success &= WriteUInt32(stream_id);
166 DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
167 return success;
168 }
169
170 bool SpdyFrameBuilder::WriteStringPiece16(const SpdyStringPiece& value) {
171 if (value.size() > 0xffff) {
172 DCHECK(false) << "Tried to write string with length > 16bit.";
173 return false;
174 }
175
176 if (!WriteUInt16(static_cast<uint16_t>(value.size()))) {
177 return false;
178 }
179
180 return WriteBytes(value.data(), static_cast<uint16_t>(value.size()));
181 }
182
183 bool SpdyFrameBuilder::WriteStringPiece32(const SpdyStringPiece& value) {
184 if (!WriteUInt32(value.size())) {
185 return false;
186 }
187
188 return WriteBytes(value.data(), value.size());
189 }
190
191 bool SpdyFrameBuilder::WriteBytes(const void* data, uint32_t data_len) {
192 if (!CanWrite(data_len)) {
193 return false;
194 }
195
196 if (output_ == nullptr) {
197 char* dest = GetWritableBuffer(data_len);
198 memcpy(dest, data, data_len);
199 Seek(data_len);
200 } else {
201 char* dest = nullptr;
202 size_t size = 0;
203 size_t total_written = 0;
204 const char* data_ptr = reinterpret_cast<const char*>(data);
205 while (data_len > 0) {
206 dest = GetWritableOutput(data_len, &size);
207 if (dest == nullptr || size == 0) {
208 // Unable to make progress.
209 return false;
210 }
211 uint32_t to_copy = std::min<uint32_t>(data_len, size);
212 const char* src = data_ptr + total_written;
213 memcpy(dest, src, to_copy);
214 Seek(to_copy);
215 data_len -= to_copy;
216 total_written += to_copy;
217 }
218 }
219 return true;
220 }
221
222 bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
223 size_t length) {
224 if (output_ != nullptr) {
225 size_t value = base::HostToNet32(length);
226 if (start_of_current_frame_ != nullptr &&
227 bytes_of_length_written_in_first_block_ == kLengthFieldLength) {
228 // Length field of the current frame is within one memory block.
229 memcpy(start_of_current_frame_, reinterpret_cast<char*>(&value) + 1,
230 kLengthFieldLength);
231 return true;
232 } else if (start_of_current_frame_ != nullptr &&
233 start_of_current_frame_in_next_block_ != nullptr &&
234 bytes_of_length_written_in_first_block_ < kLengthFieldLength) {
235 // Length field of the current frame crosses two memory blocks.
236 memcpy(start_of_current_frame_, reinterpret_cast<char*>(&value) + 1,
237 bytes_of_length_written_in_first_block_);
238 memcpy(start_of_current_frame_in_next_block_,
239 reinterpret_cast<char*>(&value) + 1 +
240 bytes_of_length_written_in_first_block_,
241 kLengthFieldLength - bytes_of_length_written_in_first_block_);
242 return true;
243 } else {
244 return false;
245 }
246 }
247
248 DCHECK_GE(framer.GetFrameMaximumSize(), length);
249 bool success = false;
250 const size_t old_length = length_;
251
252 length_ = 0;
253 success = WriteUInt24(length);
254
255 length_ = old_length;
256 return success;
257 }
258
259 bool SpdyFrameBuilder::CanWrite(size_t length) const {
260 if (length > kLengthMask) {
261 DCHECK(false);
262 return false;
263 }
264
265 if (output_ == nullptr) {
266 if (offset_ + length_ + length > capacity_) {
267 DLOG(FATAL) << "Requested: " << length << " capacity: " << capacity_
268 << " used: " << offset_ + length_;
269 return false;
270 }
271 } else {
272 if (length > output_->BytesFree()) {
273 return false;
274 }
275 }
276
277 return true;
278 }
279
280 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_frame_builder.h ('k') | net/spdy/spdy_frame_builder_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698