OSDN Git Service

Update to current version of Go library.
[pf3gnuchains/gcc-fork.git] / libgo / go / http / spdy / protocol.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package spdy is an incomplete implementation of the SPDY protocol.
6 //
7 // The implementation follows draft 2 of the spec:
8 // https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft2
9 package spdy
10
11 import (
12         "bytes"
13         "compress/zlib"
14         "encoding/binary"
15         "http"
16         "io"
17         "os"
18         "strconv"
19         "strings"
20         "sync"
21 )
22
23 // Version is the protocol version number that this package implements.
24 const Version = 2
25
26 // ControlFrameType stores the type field in a control frame header.
27 type ControlFrameType uint16
28
29 // Control frame type constants
30 const (
31         TypeSynStream    ControlFrameType = 0x0001
32         TypeSynReply     = 0x0002
33         TypeRstStream    = 0x0003
34         TypeSettings     = 0x0004
35         TypeNoop         = 0x0005
36         TypePing         = 0x0006
37         TypeGoaway       = 0x0007
38         TypeHeaders      = 0x0008
39         TypeWindowUpdate = 0x0009
40 )
41
42 func (t ControlFrameType) String() string {
43         switch t {
44         case TypeSynStream:
45                 return "SYN_STREAM"
46         case TypeSynReply:
47                 return "SYN_REPLY"
48         case TypeRstStream:
49                 return "RST_STREAM"
50         case TypeSettings:
51                 return "SETTINGS"
52         case TypeNoop:
53                 return "NOOP"
54         case TypePing:
55                 return "PING"
56         case TypeGoaway:
57                 return "GOAWAY"
58         case TypeHeaders:
59                 return "HEADERS"
60         case TypeWindowUpdate:
61                 return "WINDOW_UPDATE"
62         }
63         return "Type(" + strconv.Itoa(int(t)) + ")"
64 }
65
66 type FrameFlags uint8
67
68 // Stream frame flags
69 const (
70         FlagFin            FrameFlags = 0x01
71         FlagUnidirectional = 0x02
72 )
73
74 // SETTINGS frame flags
75 const (
76         FlagClearPreviouslyPersistedSettings FrameFlags = 0x01
77 )
78
79 // MaxDataLength is the maximum number of bytes that can be stored in one frame.
80 const MaxDataLength = 1<<24 - 1
81
82 // A Frame is a framed message as sent between clients and servers.
83 // There are two types of frames: control frames and data frames.
84 type Frame struct {
85         Header [4]byte
86         Flags  FrameFlags
87         Data   []byte
88 }
89
90 // ControlFrame creates a control frame with the given information.
91 func ControlFrame(t ControlFrameType, f FrameFlags, data []byte) Frame {
92         return Frame{
93                 Header: [4]byte{
94                         (Version&0xff00)>>8 | 0x80,
95                         (Version & 0x00ff),
96                         byte((t & 0xff00) >> 8),
97                         byte((t & 0x00ff) >> 0),
98                 },
99                 Flags: f,
100                 Data:  data,
101         }
102 }
103
104 // DataFrame creates a data frame with the given information.
105 func DataFrame(streamId uint32, f FrameFlags, data []byte) Frame {
106         return Frame{
107                 Header: [4]byte{
108                         byte(streamId & 0x7f000000 >> 24),
109                         byte(streamId & 0x00ff0000 >> 16),
110                         byte(streamId & 0x0000ff00 >> 8),
111                         byte(streamId & 0x000000ff >> 0),
112                 },
113                 Flags: f,
114                 Data:  data,
115         }
116 }
117
118 // ReadFrame reads an entire frame into memory.
119 func ReadFrame(r io.Reader) (f Frame, err os.Error) {
120         _, err = io.ReadFull(r, f.Header[:])
121         if err != nil {
122                 return
123         }
124         err = binary.Read(r, binary.BigEndian, &f.Flags)
125         if err != nil {
126                 return
127         }
128         var lengthField [3]byte
129         _, err = io.ReadFull(r, lengthField[:])
130         if err != nil {
131                 if err == os.EOF {
132                         err = io.ErrUnexpectedEOF
133                 }
134                 return
135         }
136         var length uint32
137         length |= uint32(lengthField[0]) << 16
138         length |= uint32(lengthField[1]) << 8
139         length |= uint32(lengthField[2]) << 0
140         if length > 0 {
141                 f.Data = make([]byte, int(length))
142                 _, err = io.ReadFull(r, f.Data)
143                 if err == os.EOF {
144                         err = io.ErrUnexpectedEOF
145                 }
146         } else {
147                 f.Data = []byte{}
148         }
149         return
150 }
151
152 // IsControl returns whether the frame holds a control frame.
153 func (f Frame) IsControl() bool {
154         return f.Header[0]&0x80 != 0
155 }
156
157 // Type obtains the type field if the frame is a control frame, otherwise it returns zero.
158 func (f Frame) Type() ControlFrameType {
159         if !f.IsControl() {
160                 return 0
161         }
162         return (ControlFrameType(f.Header[2])<<8 | ControlFrameType(f.Header[3]))
163 }
164
165 // StreamId returns the stream ID field if the frame is a data frame, otherwise it returns zero.
166 func (f Frame) StreamId() (id uint32) {
167         if f.IsControl() {
168                 return 0
169         }
170         id |= uint32(f.Header[0]) << 24
171         id |= uint32(f.Header[1]) << 16
172         id |= uint32(f.Header[2]) << 8
173         id |= uint32(f.Header[3]) << 0
174         return
175 }
176
177 // WriteTo writes the frame in the SPDY format.
178 func (f Frame) WriteTo(w io.Writer) (n int64, err os.Error) {
179         var nn int
180         // Header
181         nn, err = w.Write(f.Header[:])
182         n += int64(nn)
183         if err != nil {
184                 return
185         }
186         // Flags
187         nn, err = w.Write([]byte{byte(f.Flags)})
188         n += int64(nn)
189         if err != nil {
190                 return
191         }
192         // Length
193         nn, err = w.Write([]byte{
194                 byte(len(f.Data) & 0x00ff0000 >> 16),
195                 byte(len(f.Data) & 0x0000ff00 >> 8),
196                 byte(len(f.Data) & 0x000000ff),
197         })
198         n += int64(nn)
199         if err != nil {
200                 return
201         }
202         // Data
203         if len(f.Data) > 0 {
204                 nn, err = w.Write(f.Data)
205                 n += int64(nn)
206         }
207         return
208 }
209
210 // headerDictionary is the dictionary sent to the zlib compressor/decompressor.
211 // Even though the specification states there is no null byte at the end, Chrome sends it.
212 const headerDictionary = "optionsgetheadpostputdeletetrace" +
213         "acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
214         "if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
215         "max-forwardsproxy-authorizationrangerefererteuser-agent" +
216         "100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
217         "accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
218         "servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
219         "connectiondatetrailertransfer-encodingupgradeviawarning" +
220         "content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
221         "MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
222         "JanFebMarAprMayJunJulAugSepOctNovDec" +
223         "chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
224         "charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"
225
226 // hrSource is a reader that passes through reads from another reader.
227 // When the underlying reader reaches EOF, Read will block until another reader is added via change.
228 type hrSource struct {
229         r io.Reader
230         m sync.RWMutex
231         c *sync.Cond
232 }
233
234 func (src *hrSource) Read(p []byte) (n int, err os.Error) {
235         src.m.RLock()
236         for src.r == nil {
237                 src.c.Wait()
238         }
239         n, err = src.r.Read(p)
240         src.m.RUnlock()
241         if err == os.EOF {
242                 src.change(nil)
243                 err = nil
244         }
245         return
246 }
247
248 func (src *hrSource) change(r io.Reader) {
249         src.m.Lock()
250         defer src.m.Unlock()
251         src.r = r
252         src.c.Broadcast()
253 }
254
255 // A HeaderReader reads zlib-compressed headers.
256 type HeaderReader struct {
257         source       hrSource
258         decompressor io.ReadCloser
259 }
260
261 // NewHeaderReader creates a HeaderReader with the initial dictionary.
262 func NewHeaderReader() (hr *HeaderReader) {
263         hr = new(HeaderReader)
264         hr.source.c = sync.NewCond(hr.source.m.RLocker())
265         return
266 }
267
268 // ReadHeader reads a set of headers from a reader.
269 func (hr *HeaderReader) ReadHeader(r io.Reader) (h http.Header, err os.Error) {
270         hr.source.change(r)
271         h, err = hr.read()
272         return
273 }
274
275 // Decode reads a set of headers from a block of bytes.
276 func (hr *HeaderReader) Decode(data []byte) (h http.Header, err os.Error) {
277         hr.source.change(bytes.NewBuffer(data))
278         h, err = hr.read()
279         return
280 }
281
282 func (hr *HeaderReader) read() (h http.Header, err os.Error) {
283         var count uint16
284         if hr.decompressor == nil {
285                 hr.decompressor, err = zlib.NewReaderDict(&hr.source, []byte(headerDictionary))
286                 if err != nil {
287                         return
288                 }
289         }
290         err = binary.Read(hr.decompressor, binary.BigEndian, &count)
291         if err != nil {
292                 return
293         }
294         h = make(http.Header, int(count))
295         for i := 0; i < int(count); i++ {
296                 var name, value string
297                 name, err = readHeaderString(hr.decompressor)
298                 if err != nil {
299                         return
300                 }
301                 value, err = readHeaderString(hr.decompressor)
302                 if err != nil {
303                         return
304                 }
305                 valueList := strings.Split(string(value), "\x00", -1)
306                 for _, v := range valueList {
307                         h.Add(name, v)
308                 }
309         }
310         return
311 }
312
313 func readHeaderString(r io.Reader) (s string, err os.Error) {
314         var length uint16
315         err = binary.Read(r, binary.BigEndian, &length)
316         if err != nil {
317                 return
318         }
319         data := make([]byte, int(length))
320         _, err = io.ReadFull(r, data)
321         if err != nil {
322                 return
323         }
324         return string(data), nil
325 }
326
327 // HeaderWriter will write zlib-compressed headers on different streams.
328 type HeaderWriter struct {
329         compressor *zlib.Writer
330         buffer     *bytes.Buffer
331 }
332
333 // NewHeaderWriter creates a HeaderWriter ready to compress headers.
334 func NewHeaderWriter(level int) (hw *HeaderWriter) {
335         hw = &HeaderWriter{buffer: new(bytes.Buffer)}
336         hw.compressor, _ = zlib.NewWriterDict(hw.buffer, level, []byte(headerDictionary))
337         return
338 }
339
340 // WriteHeader writes a header block directly to an output.
341 func (hw *HeaderWriter) WriteHeader(w io.Writer, h http.Header) (err os.Error) {
342         hw.write(h)
343         _, err = io.Copy(w, hw.buffer)
344         hw.buffer.Reset()
345         return
346 }
347
348 // Encode returns a compressed header block.
349 func (hw *HeaderWriter) Encode(h http.Header) (data []byte) {
350         hw.write(h)
351         data = make([]byte, hw.buffer.Len())
352         hw.buffer.Read(data)
353         return
354 }
355
356 func (hw *HeaderWriter) write(h http.Header) {
357         binary.Write(hw.compressor, binary.BigEndian, uint16(len(h)))
358         for k, vals := range h {
359                 k = strings.ToLower(k)
360                 binary.Write(hw.compressor, binary.BigEndian, uint16(len(k)))
361                 binary.Write(hw.compressor, binary.BigEndian, []byte(k))
362                 v := strings.Join(vals, "\x00")
363                 binary.Write(hw.compressor, binary.BigEndian, uint16(len(v)))
364                 binary.Write(hw.compressor, binary.BigEndian, []byte(v))
365         }
366         hw.compressor.Flush()
367 }