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.
5 #include "net/spdy/spdy_frame_builder.h"
9 #include "base/logging.h"
10 #include "net/spdy/spdy_framer.h"
11 #include "net/spdy/spdy_protocol.h"
17 // A special structure for the 8 bit flags and 24 bit length fields.
18 union FlagsAndLength
{
19 uint8 flags
[4]; // 8 bits
20 uint32 length
; // 24 bits
23 // Creates a FlagsAndLength.
24 FlagsAndLength
CreateFlagsAndLength(uint8 flags
, size_t length
) {
25 DCHECK_EQ(0u, length
& ~static_cast<size_t>(kLengthMask
));
26 FlagsAndLength flags_length
;
27 flags_length
.length
= htonl(static_cast<uint32
>(length
));
28 DCHECK_EQ(0, flags
& ~kControlFlagsMask
);
29 flags_length
.flags
[0] = flags
;
35 SpdyFrameBuilder::SpdyFrameBuilder(size_t size
, SpdyMajorVersion version
)
36 : buffer_(new char[size
]),
43 SpdyFrameBuilder::~SpdyFrameBuilder() {
46 char* SpdyFrameBuilder::GetWritableBuffer(size_t length
) {
47 if (!CanWrite(length
)) {
50 return buffer_
.get() + offset_
+ length_
;
53 bool SpdyFrameBuilder::Seek(size_t length
) {
54 if (!CanWrite(length
)) {
62 bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer
& framer
,
65 DCHECK_GE(SPDY3
, version_
);
66 DCHECK(SpdyConstants::IsValidFrameType(
67 version_
, SpdyConstants::SerializeFrameType(version_
, type
)));
69 FlagsAndLength flags_length
= CreateFlagsAndLength(
70 flags
, capacity_
- framer
.GetControlFrameHeaderSize());
71 success
&= WriteUInt16(kControlFlagMask
|
72 SpdyConstants::SerializeMajorVersion(version_
));
73 success
&= WriteUInt16(
74 SpdyConstants::SerializeFrameType(framer
.protocol_version(), type
));
75 success
&= WriteBytes(&flags_length
, sizeof(flags_length
));
76 DCHECK_EQ(framer
.GetControlFrameHeaderSize(), length());
80 bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer
& framer
,
81 SpdyStreamId stream_id
,
83 if (version_
> SPDY3
) {
84 return BeginNewFrame(framer
, DATA
, flags
, stream_id
);
86 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
88 success
&= WriteUInt32(stream_id
);
89 size_t length_field
= capacity_
- framer
.GetDataFrameMinimumSize();
90 DCHECK_EQ(0u, length_field
& ~static_cast<size_t>(kLengthMask
));
91 FlagsAndLength flags_length
;
92 flags_length
.length
= htonl(length_field
);
93 DCHECK_EQ(0, flags
& ~kDataFlagsMask
);
94 flags_length
.flags
[0] = flags
;
95 success
&= WriteBytes(&flags_length
, sizeof(flags_length
));
96 DCHECK_EQ(framer
.GetDataFrameMinimumSize(), length());
100 bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer
& framer
,
103 SpdyStreamId stream_id
) {
104 DCHECK(SpdyConstants::IsValidFrameType(
105 version_
, SpdyConstants::SerializeFrameType(version_
, type
)));
106 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
107 DCHECK_GT(framer
.protocol_version(), SPDY3
);
110 // Update length field for previous frame.
111 OverwriteLength(framer
, length_
- framer
.GetPrefixLength(type
));
112 DLOG_IF(DFATAL
, SpdyConstants::GetFrameMaximumSize(version_
) < length_
)
113 << "Frame length " << length_
114 << " is longer than the maximum allowed length.";
120 // Assume all remaining capacity will be used for this frame. If not,
121 // the length will get overwritten when we begin the next frame.
122 // Don't check for length limits here because this may be larger than the
123 // actual frame length.
124 success
&= WriteUInt24(capacity_
- offset_
- framer
.GetPrefixLength(type
));
125 success
&= WriteUInt8(
126 SpdyConstants::SerializeFrameType(version_
, type
));
127 success
&= WriteUInt8(flags
);
128 success
&= WriteUInt32(stream_id
);
129 DCHECK_EQ(framer
.GetDataFrameMinimumSize(), length_
);
133 bool SpdyFrameBuilder::WriteStringPiece16(const base::StringPiece
& value
) {
134 if (value
.size() > 0xffff) {
135 DCHECK(false) << "Tried to write string with length > 16bit.";
139 if (!WriteUInt16(static_cast<uint16
>(value
.size()))) {
143 return WriteBytes(value
.data(), static_cast<uint16
>(value
.size()));
146 bool SpdyFrameBuilder::WriteStringPiece32(const base::StringPiece
& value
) {
147 if (!WriteUInt32(value
.size())) {
151 return WriteBytes(value
.data(), value
.size());
154 bool SpdyFrameBuilder::WriteBytes(const void* data
, uint32 data_len
) {
155 if (!CanWrite(data_len
)) {
159 char* dest
= GetWritableBuffer(data_len
);
160 memcpy(dest
, data
, data_len
);
165 bool SpdyFrameBuilder::RewriteLength(const SpdyFramer
& framer
) {
166 return OverwriteLength(framer
,
167 length_
- framer
.GetControlFrameHeaderSize());
170 bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer
& framer
,
172 if (version_
< HTTP2
) {
174 SpdyConstants::GetFrameMaximumSize(version_
) -
175 framer
.GetFrameMinimumSize());
177 DCHECK_LE(length
, SpdyConstants::GetFrameMaximumSize(version_
));
179 bool success
= false;
180 const size_t old_length
= length_
;
182 if (version_
< HTTP2
) {
183 FlagsAndLength flags_length
= CreateFlagsAndLength(
184 0, // We're not writing over the flags value anyway.
187 // Write into the correct location by temporarily faking the offset.
188 length_
= 5; // Offset at which the length field occurs.
189 success
= WriteBytes(reinterpret_cast<char*>(&flags_length
) + 1,
190 sizeof(flags_length
) - 1);
193 success
= WriteUInt24(length
);
196 length_
= old_length
;
200 bool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer
& framer
,
202 DCHECK_GT(framer
.protocol_version(), SPDY3
);
203 bool success
= false;
204 const size_t old_length
= length_
;
205 // Flags are the fifth octet in the frame prefix.
207 success
= WriteUInt8(flags
);
208 length_
= old_length
;
212 bool SpdyFrameBuilder::CanWrite(size_t length
) const {
213 if (length
> kLengthMask
) {
218 if (offset_
+ length_
+ length
> capacity_
) {