Skip to content

Commit db84e63

Browse files
Merge pull request #3 from marten-seemann/partial-writes
handle partial writes
2 parents 5652e3a + 8eb0a96 commit db84e63

File tree

4 files changed

+230
-120
lines changed

4 files changed

+230
-120
lines changed

decoder.go

Lines changed: 104 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package qpack
22

33
import (
4+
"bytes"
45
"errors"
56
"fmt"
67

@@ -26,12 +27,28 @@ func (e invalidIndexError) Error() string {
2627

2728
var errNoDynamicTable = decodingError{errors.New("no dynamic table")}
2829

30+
// errNeedMore is an internal sentinel error value that means the
31+
// buffer is truncated and we need to read more data before we can
32+
// continue parsing.
33+
var errNeedMore = errors.New("need more data")
34+
2935
// A Decoder is the decoding context for incremental processing of
3036
// header blocks.
3137
type Decoder struct {
3238
emitFunc func(f HeaderField)
3339

34-
buf []byte
40+
readRequiredInsertCount bool
41+
readDeltaBase bool
42+
43+
// buf is the unparsed buffer. It's only written to
44+
// saveBuf if it was truncated in the middle of a header
45+
// block. Because it's usually not owned, we can only
46+
// process it under Write.
47+
buf []byte // not owned; only valid during Write
48+
49+
// saveBuf is previous data passed to Write which we weren't able
50+
// to fully parse before. Unlike buf, we own this data.
51+
saveBuf bytes.Buffer
3552
}
3653

3754
// NewDecoder returns a new decoder
@@ -42,32 +59,69 @@ func NewDecoder(emitFunc func(f HeaderField)) *Decoder {
4259
}
4360

4461
func (d *Decoder) Write(p []byte) (int, error) {
45-
// TODO: handle incomplete writes
46-
d.buf = p
62+
if len(p) == 0 {
63+
return 0, nil
64+
}
65+
66+
// Only copy the data if we have to. Optimistically assume
67+
// that p will contain a complete header block.
68+
if d.saveBuf.Len() == 0 {
69+
d.buf = p
70+
} else {
71+
d.saveBuf.Write(p)
72+
d.buf = d.saveBuf.Bytes()
73+
d.saveBuf.Reset()
74+
}
4775

4876
if err := d.decode(); err != nil {
49-
return 0, err
77+
if err != errNeedMore {
78+
return 0, err
79+
}
80+
// TODO: limit the size of the buffer
81+
d.saveBuf.Write(d.buf)
5082
}
5183
return len(p), nil
5284
}
5385

54-
func (d *Decoder) decode() error {
55-
requiredInsertCount, rest, err := readVarInt(8, d.buf)
56-
if err != nil {
57-
return err
86+
// Close declares that the decoding is complete and resets the Decoder
87+
// to be reused again for a new header block. If there is any remaining
88+
// data in the decoder's buffer, Close returns an error.
89+
func (d *Decoder) Close() error {
90+
if d.saveBuf.Len() > 0 {
91+
d.saveBuf.Reset()
92+
return decodingError{errors.New("truncated headers")}
5893
}
59-
if requiredInsertCount != 0 {
60-
return decodingError{errors.New("expected Required Insert Count to be zero")}
94+
d.readRequiredInsertCount = false
95+
d.readDeltaBase = false
96+
return nil
97+
}
98+
99+
func (d *Decoder) decode() error {
100+
if !d.readRequiredInsertCount {
101+
requiredInsertCount, rest, err := readVarInt(8, d.buf)
102+
if err != nil {
103+
return err
104+
}
105+
d.readRequiredInsertCount = true
106+
if requiredInsertCount != 0 {
107+
return decodingError{errors.New("expected Required Insert Count to be zero")}
108+
}
109+
d.buf = rest
61110
}
62-
d.buf = rest
63-
base, rest, err := readVarInt(7, d.buf)
64-
if err != nil {
65-
return err
111+
if !d.readDeltaBase {
112+
base, rest, err := readVarInt(7, d.buf)
113+
if err != nil {
114+
return err
115+
}
116+
d.readDeltaBase = true
117+
if base != 0 {
118+
return decodingError{errors.New("expected Base to be zero")}
119+
}
120+
d.buf = rest
66121
}
67-
if base != 0 {
68-
return decodingError{errors.New("expected Base to be zero")}
122+
if len(d.buf) == 0 {
123+
return errNeedMore
69124
}
70-
d.buf = rest
71125

72126
for len(d.buf) > 0 {
73127
b := d.buf[0]
@@ -80,7 +134,7 @@ func (d *Decoder) decode() error {
80134
case b&0xe0 == 0x20: // 001xxxxx
81135
err = d.parseLiteralHeaderFieldWithoutNameReference()
82136
default:
83-
err = fmt.Errorf("unexpected type byte: %#x", d.buf[0])
137+
err = fmt.Errorf("unexpected type byte: %#x", b)
84138
}
85139
if err != nil {
86140
return err
@@ -90,91 +144,90 @@ func (d *Decoder) decode() error {
90144
}
91145

92146
func (d *Decoder) parseIndexedHeaderField() error {
93-
if d.buf[0]&0x40 == 0 {
147+
buf := d.buf
148+
if buf[0]&0x40 == 0 {
94149
return errNoDynamicTable
95150
}
96-
index, rest, err := readVarInt(6, d.buf)
151+
index, buf, err := readVarInt(6, buf)
97152
if err != nil {
98153
return err
99154
}
100-
d.buf = rest
101155
hf, ok := d.at(index)
102156
if !ok {
103157
return decodingError{invalidIndexError(index)}
104158
}
105159
d.emitFunc(hf)
160+
d.buf = buf
106161
return nil
107162
}
108163

109164
func (d *Decoder) parseLiteralHeaderField() error {
110-
if d.buf[0]&0x20 > 0 || d.buf[0]&0x10 == 0 {
165+
buf := d.buf
166+
if buf[0]&0x20 > 0 || buf[0]&0x10 == 0 {
111167
return errNoDynamicTable
112168
}
113-
index, rest, err := readVarInt(4, d.buf)
169+
index, buf, err := readVarInt(4, buf)
114170
if err != nil {
115171
return err
116172
}
117-
d.buf = rest
118173
hf, ok := d.at(index)
119174
if !ok {
120175
return decodingError{invalidIndexError(index)}
121176
}
122-
usesHuffman := d.buf[0]&0x80 > 0
123-
l, rest, err := readVarInt(7, d.buf)
124-
if err != nil {
125-
return err
177+
if len(buf) == 0 {
178+
return errNeedMore
126179
}
127-
d.buf = rest
128-
val, err := d.parseString(l, usesHuffman)
180+
usesHuffman := buf[0]&0x80 > 0
181+
val, buf, err := d.readString(buf, 7, usesHuffman)
129182
if err != nil {
130183
return err
131184
}
132185
hf.Value = val
133186
d.emitFunc(hf)
187+
d.buf = buf
134188
return nil
135189
}
136190

137191
func (d *Decoder) parseLiteralHeaderFieldWithoutNameReference() error {
138-
usesHuffmanForName := d.buf[0]&0x8 > 0
139-
nameLen, rest, err := readVarInt(3, d.buf)
140-
if err != nil {
141-
return err
142-
}
143-
d.buf = rest
144-
name, err := d.parseString(nameLen, usesHuffmanForName)
192+
buf := d.buf
193+
usesHuffmanForName := buf[0]&0x8 > 0
194+
name, buf, err := d.readString(buf, 3, usesHuffmanForName)
145195
if err != nil {
146196
return err
147197
}
148-
usesHuffmanForVal := d.buf[0]&0x80 > 0
149-
valLen, rest, err := readVarInt(7, d.buf)
150-
if err != nil {
151-
return err
198+
if len(buf) == 0 {
199+
return errNeedMore
152200
}
153-
d.buf = rest
154-
val, err := d.parseString(valLen, usesHuffmanForVal)
201+
usesHuffmanForVal := buf[0]&0x80 > 0
202+
val, buf, err := d.readString(buf, 7, usesHuffmanForVal)
155203
if err != nil {
156204
return err
157205
}
158206
d.emitFunc(HeaderField{Name: name, Value: val})
207+
d.buf = buf
159208
return nil
160209
}
161210

162-
func (d *Decoder) parseString(l uint64, usesHuffman bool) (string, error) {
163-
if uint64(len(d.buf)) < l {
164-
return "", errors.New("too little data")
211+
func (d *Decoder) readString(buf []byte, n uint8, usesHuffman bool) (string, []byte, error) {
212+
l, buf, err := readVarInt(n, buf)
213+
if err != nil {
214+
return "", nil, err
215+
}
216+
if uint64(len(buf)) < l {
217+
return "", nil, errNeedMore
165218
}
166219
var val string
167220
if usesHuffman {
168221
var err error
169-
val, err = hpack.HuffmanDecodeToString(d.buf[:l])
222+
val, err = hpack.HuffmanDecodeToString(buf[:l])
170223
if err != nil {
171-
return "", err
224+
return "", nil, err
172225
}
173226
} else {
174-
val = string(d.buf[:l])
227+
val = string(buf[:l])
175228
}
176-
d.buf = d.buf[l:]
177-
return val, nil
229+
buf = buf[l:]
230+
return val, buf, nil
178231
}
179232

180233
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {

0 commit comments

Comments
 (0)