write.go 7.9 KB

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