Update Go library to last weekly.
[platform/upstream/gcc.git] / libgo / go / exp / spdy / write.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
6
7 import (
8         "encoding/binary"
9         "http"
10         "io"
11         "os"
12         "strings"
13 )
14
15 func (frame *SynStreamFrame) write(f *Framer) os.Error {
16         return f.writeSynStreamFrame(frame)
17 }
18
19 func (frame *SynReplyFrame) write(f *Framer) os.Error {
20         return f.writeSynReplyFrame(frame)
21 }
22
23 func (frame *RstStreamFrame) write(f *Framer) (err os.Error) {
24         frame.CFHeader.version = Version
25         frame.CFHeader.frameType = TypeRstStream
26         frame.CFHeader.length = 8
27
28         // Serialize frame to Writer
29         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
30                 return
31         }
32         if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
33                 return
34         }
35         if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
36                 return
37         }
38         return
39 }
40
41 func (frame *SettingsFrame) write(f *Framer) (err os.Error) {
42         frame.CFHeader.version = Version
43         frame.CFHeader.frameType = TypeSettings
44         frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
45
46         // Serialize frame to Writer
47         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
48                 return
49         }
50         if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
51                 return
52         }
53         for _, flagIdValue := range frame.FlagIdValues {
54                 flagId := (uint32(flagIdValue.Flag) << 24) | uint32(flagIdValue.Id)
55                 if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
56                         return
57                 }
58                 if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
59                         return
60                 }
61         }
62         return
63 }
64
65 func (frame *NoopFrame) write(f *Framer) os.Error {
66         frame.CFHeader.version = Version
67         frame.CFHeader.frameType = TypeNoop
68
69         // Serialize frame to Writer
70         return writeControlFrameHeader(f.w, frame.CFHeader)
71 }
72
73 func (frame *PingFrame) write(f *Framer) (err os.Error) {
74         frame.CFHeader.version = Version
75         frame.CFHeader.frameType = TypePing
76         frame.CFHeader.length = 4
77
78         // Serialize frame to Writer
79         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
80                 return
81         }
82         if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
83                 return
84         }
85         return
86 }
87
88 func (frame *GoAwayFrame) write(f *Framer) (err os.Error) {
89         frame.CFHeader.version = Version
90         frame.CFHeader.frameType = TypeGoAway
91         frame.CFHeader.length = 4
92
93         // Serialize frame to Writer
94         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
95                 return
96         }
97         if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
98                 return
99         }
100         return nil
101 }
102
103 func (frame *HeadersFrame) write(f *Framer) os.Error {
104         return f.writeHeadersFrame(frame)
105 }
106
107 func (frame *DataFrame) write(f *Framer) os.Error {
108         return f.writeDataFrame(frame)
109 }
110
111 // WriteFrame writes a frame.
112 func (f *Framer) WriteFrame(frame Frame) os.Error {
113         return frame.write(f)
114 }
115
116 func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) os.Error {
117         if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
118                 return err
119         }
120         if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
121                 return err
122         }
123         flagsAndLength := (uint32(h.Flags) << 24) | h.length
124         if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
125                 return err
126         }
127         return nil
128 }
129
130 func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err os.Error) {
131         n = 0
132         if err = binary.Write(w, binary.BigEndian, uint16(len(h))); err != nil {
133                 return
134         }
135         n += 2
136         for name, values := range h {
137                 if err = binary.Write(w, binary.BigEndian, uint16(len(name))); err != nil {
138                         return
139                 }
140                 n += 2
141                 name = strings.ToLower(name)
142                 if _, err = io.WriteString(w, name); err != nil {
143                         return
144                 }
145                 n += len(name)
146                 v := strings.Join(values, "\x00")
147                 if err = binary.Write(w, binary.BigEndian, uint16(len(v))); err != nil {
148                         return
149                 }
150                 n += 2
151                 if _, err = io.WriteString(w, v); err != nil {
152                         return
153                 }
154                 n += len(v)
155         }
156         return
157 }
158
159 func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err os.Error) {
160         // Marshal the headers.
161         var writer io.Writer = f.headerBuf
162         if !f.headerCompressionDisabled {
163                 writer = f.headerCompressor
164         }
165         if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
166                 return
167         }
168         if !f.headerCompressionDisabled {
169                 f.headerCompressor.Flush()
170         }
171
172         // Set ControlFrameHeader
173         frame.CFHeader.version = Version
174         frame.CFHeader.frameType = TypeSynStream
175         frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
176
177         // Serialize frame to Writer
178         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
179                 return err
180         }
181         if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
182                 return err
183         }
184         if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
185                 return err
186         }
187         if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<14); err != nil {
188                 return err
189         }
190         if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
191                 return err
192         }
193         f.headerBuf.Reset()
194         return nil
195 }
196
197 func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err os.Error) {
198         // Marshal the headers.
199         var writer io.Writer = f.headerBuf
200         if !f.headerCompressionDisabled {
201                 writer = f.headerCompressor
202         }
203         if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
204                 return
205         }
206         if !f.headerCompressionDisabled {
207                 f.headerCompressor.Flush()
208         }
209
210         // Set ControlFrameHeader
211         frame.CFHeader.version = Version
212         frame.CFHeader.frameType = TypeSynReply
213         frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
214
215         // Serialize frame to Writer
216         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
217                 return
218         }
219         if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
220                 return
221         }
222         if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
223                 return
224         }
225         if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
226                 return
227         }
228         f.headerBuf.Reset()
229         return
230 }
231
232 func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err os.Error) {
233         // Marshal the headers.
234         var writer io.Writer = f.headerBuf
235         if !f.headerCompressionDisabled {
236                 writer = f.headerCompressor
237         }
238         if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
239                 return
240         }
241         if !f.headerCompressionDisabled {
242                 f.headerCompressor.Flush()
243         }
244
245         // Set ControlFrameHeader
246         frame.CFHeader.version = Version
247         frame.CFHeader.frameType = TypeHeaders
248         frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
249
250         // Serialize frame to Writer
251         if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
252                 return
253         }
254         if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
255                 return
256         }
257         if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
258                 return
259         }
260         if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
261                 return
262         }
263         f.headerBuf.Reset()
264         return
265 }
266
267 func (f *Framer) writeDataFrame(frame *DataFrame) (err os.Error) {
268         // Validate DataFrame
269         if frame.StreamId&0x80000000 != 0 || len(frame.Data) >= 0x0f000000 {
270                 return &Error{InvalidDataFrame, frame.StreamId}
271         }
272
273         // Serialize frame to Writer
274         if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
275                 return
276         }
277         flagsAndLength := (uint32(frame.Flags) << 24) | uint32(len(frame.Data))
278         if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
279                 return
280         }
281         if _, err = f.w.Write(frame.Data); err != nil {
282                 return
283         }
284
285         return nil
286 }