OLD | NEW |
| (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 #ifndef NET_SPDY_SPDY_FRAME_BUILDER_H_ | |
6 #define NET_SPDY_SPDY_FRAME_BUILDER_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <memory> | |
12 | |
13 #include "base/gtest_prod_util.h" | |
14 #include "base/sys_byteorder.h" | |
15 #include "net/base/net_export.h" | |
16 #include "net/spdy/platform/api/spdy_string_piece.h" | |
17 #include "net/spdy/spdy_bug_tracker.h" | |
18 #include "net/spdy/spdy_protocol.h" | |
19 #include "net/spdy/zero_copy_output_buffer.h" | |
20 | |
21 namespace net { | |
22 | |
23 class SpdyFramer; | |
24 | |
25 // This class provides facilities for basic binary value packing | |
26 // into Spdy frames. | |
27 // | |
28 // The SpdyFrameBuilder supports appending primitive values (int, string, etc) | |
29 // to a frame instance. The SpdyFrameBuilder grows its internal memory buffer | |
30 // dynamically to hold the sequence of primitive values. The internal memory | |
31 // buffer is exposed as the "data" of the SpdyFrameBuilder. | |
32 class NET_EXPORT_PRIVATE SpdyFrameBuilder { | |
33 public: | |
34 // Initializes a SpdyFrameBuilder with a buffer of given size | |
35 explicit SpdyFrameBuilder(size_t size); | |
36 // Doesn't take ownership of output. | |
37 SpdyFrameBuilder(size_t size, ZeroCopyOutputBuffer* output); | |
38 | |
39 ~SpdyFrameBuilder(); | |
40 | |
41 // Returns the total size of the SpdyFrameBuilder's data, which may include | |
42 // multiple frames. | |
43 size_t length() const { return offset_ + length_; } | |
44 | |
45 // Seeks forward by the given number of bytes. Useful in conjunction with | |
46 // GetWriteableBuffer() above. | |
47 bool Seek(size_t length); | |
48 | |
49 // Populates this frame with a HTTP2 frame prefix using length information | |
50 // from |capacity_|. The given type must be a control frame type. | |
51 bool BeginNewFrame(const SpdyFramer& framer, | |
52 SpdyFrameType type, | |
53 uint8_t flags, | |
54 SpdyStreamId stream_id); | |
55 | |
56 // Populates this frame with a HTTP2 frame prefix with type and length | |
57 // information. |type| must be a defined type. | |
58 bool BeginNewFrame(const SpdyFramer& framer, | |
59 SpdyFrameType type, | |
60 uint8_t flags, | |
61 SpdyStreamId stream_id, | |
62 size_t length); | |
63 | |
64 // Populates this frame with a HTTP2 frame prefix with type and length | |
65 // information. |raw_frame_type| must not be a defined frame type. | |
66 bool BeginNewExtensionFrame(const SpdyFramer& framer, | |
67 uint8_t raw_frame_type, | |
68 uint8_t flags, | |
69 SpdyStreamId stream_id, | |
70 size_t length); | |
71 | |
72 // Takes the buffer from the SpdyFrameBuilder. | |
73 SpdySerializedFrame take() { | |
74 SPDY_BUG_IF(output_ != nullptr) << "ZeroCopyOutputBuffer is used to build " | |
75 << "frames. take() shouldn't be called"; | |
76 SPDY_BUG_IF(kMaxFrameSizeLimit < length_) | |
77 << "Frame length " << length_ | |
78 << " is longer than the maximum possible allowed length."; | |
79 SpdySerializedFrame rv(buffer_.release(), length(), true); | |
80 capacity_ = 0; | |
81 length_ = 0; | |
82 offset_ = 0; | |
83 return rv; | |
84 } | |
85 | |
86 // Methods for adding to the payload. These values are appended to the end | |
87 // of the SpdyFrameBuilder payload. Note - binary integers are converted from | |
88 // host to network form. | |
89 bool WriteUInt8(uint8_t value) { return WriteBytes(&value, sizeof(value)); } | |
90 bool WriteUInt16(uint16_t value) { | |
91 value = base::HostToNet16(value); | |
92 return WriteBytes(&value, sizeof(value)); | |
93 } | |
94 bool WriteUInt24(uint32_t value) { | |
95 value = base::HostToNet32(value); | |
96 return WriteBytes(reinterpret_cast<char*>(&value) + 1, | |
97 sizeof(value) - 1); | |
98 } | |
99 bool WriteUInt32(uint32_t value) { | |
100 value = base::HostToNet32(value); | |
101 return WriteBytes(&value, sizeof(value)); | |
102 } | |
103 bool WriteUInt64(uint64_t value) { | |
104 uint32_t upper = base::HostToNet32(static_cast<uint32_t>(value >> 32)); | |
105 uint32_t lower = base::HostToNet32(static_cast<uint32_t>(value)); | |
106 return (WriteBytes(&upper, sizeof(upper)) && | |
107 WriteBytes(&lower, sizeof(lower))); | |
108 } | |
109 bool WriteStringPiece16(const SpdyStringPiece& value); | |
110 bool WriteStringPiece32(const SpdyStringPiece& value); | |
111 bool WriteBytes(const void* data, uint32_t data_len); | |
112 | |
113 // Update (in-place) the length field in the frame being built to reflect the | |
114 // given length. | |
115 // The framer parameter is used to determine version-specific location and | |
116 // size information of the length field to be written, and must be initialized | |
117 // with the correct version for the frame being written. | |
118 bool OverwriteLength(const SpdyFramer& framer, size_t length); | |
119 | |
120 private: | |
121 FRIEND_TEST_ALL_PREFIXES(SpdyFrameBuilderTest, GetWritableBuffer); | |
122 FRIEND_TEST_ALL_PREFIXES(SpdyFrameBuilderTest, GetWritableOutput); | |
123 FRIEND_TEST_ALL_PREFIXES(SpdyFrameBuilderTest, GetWritableOutputNegative); | |
124 | |
125 // Populates this frame with a HTTP2 frame prefix with type and length | |
126 // information. | |
127 bool BeginNewFrameInternal(const SpdyFramer& framer, | |
128 uint8_t raw_frame_type, | |
129 uint8_t flags, | |
130 SpdyStreamId stream_id, | |
131 size_t length); | |
132 | |
133 // Returns a writeable buffer of given size in bytes, to be appended to the | |
134 // currently written frame. Does bounds checking on length but does not | |
135 // increment the underlying iterator. To do so, consumers should subsequently | |
136 // call Seek(). | |
137 // In general, consumers should use Write*() calls instead of this. | |
138 // Returns NULL on failure. | |
139 char* GetWritableBuffer(size_t length); | |
140 char* GetWritableOutput(size_t desired_length, size_t* actual_length); | |
141 | |
142 // Checks to make sure that there is an appropriate amount of space for a | |
143 // write of given size, in bytes. | |
144 bool CanWrite(size_t length) const; | |
145 | |
146 // A buffer to be created whenever a new frame needs to be written. Used only | |
147 // if |output_| is nullptr. | |
148 std::unique_ptr<char[]> buffer_; | |
149 // A pre-allocated buffer. If not-null, serialized frame data is written to | |
150 // this buffer. | |
151 ZeroCopyOutputBuffer* output_ = nullptr; // Does not own. | |
152 | |
153 size_t capacity_; // Allocation size of payload, set by constructor. | |
154 size_t length_; // Length of the latest frame in the buffer. | |
155 size_t offset_; // Position at which the latest frame begins. | |
156 | |
157 // Remove all four below after | |
158 // FLAGS_chromium_http2_flag_remove_rewritelength deprecates. | |
159 const size_t kLengthFieldLength = 3; | |
160 char* start_of_current_frame_ = nullptr; | |
161 size_t bytes_of_length_written_in_first_block_ = kLengthFieldLength; | |
162 // In case length of a new frame is cross blocks. | |
163 char* start_of_current_frame_in_next_block_ = nullptr; | |
164 }; | |
165 | |
166 } // namespace net | |
167 | |
168 #endif // NET_SPDY_SPDY_FRAME_BUILDER_H_ | |
OLD | NEW |