OSDN Git Service

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