...

Source file src/github.com/moby/spdystream/spdy/write.go

Documentation: github.com/moby/spdystream/spdy

     1  /*
     2     Copyright 2014-2021 Docker Inc.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  // Copyright 2011 The Go Authors. All rights reserved.
    18  // Use of this source code is governed by a BSD-style
    19  // license that can be found in the LICENSE file.
    20  
    21  package spdy
    22  
    23  import (
    24  	"encoding/binary"
    25  	"io"
    26  	"net/http"
    27  	"strings"
    28  )
    29  
    30  func (frame *SynStreamFrame) write(f *Framer) error {
    31  	return f.writeSynStreamFrame(frame)
    32  }
    33  
    34  func (frame *SynReplyFrame) write(f *Framer) error {
    35  	return f.writeSynReplyFrame(frame)
    36  }
    37  
    38  func (frame *RstStreamFrame) write(f *Framer) (err error) {
    39  	if frame.StreamId == 0 {
    40  		return &Error{ZeroStreamId, 0}
    41  	}
    42  	frame.CFHeader.version = Version
    43  	frame.CFHeader.frameType = TypeRstStream
    44  	frame.CFHeader.Flags = 0
    45  	frame.CFHeader.length = 8
    46  
    47  	// Serialize frame to Writer.
    48  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
    49  		return
    50  	}
    51  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
    52  		return
    53  	}
    54  	if frame.Status == 0 {
    55  		return &Error{InvalidControlFrame, frame.StreamId}
    56  	}
    57  	if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
    58  		return
    59  	}
    60  	return
    61  }
    62  
    63  func (frame *SettingsFrame) write(f *Framer) (err error) {
    64  	frame.CFHeader.version = Version
    65  	frame.CFHeader.frameType = TypeSettings
    66  	frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
    67  
    68  	// Serialize frame to Writer.
    69  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
    70  		return
    71  	}
    72  	if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
    73  		return
    74  	}
    75  	for _, flagIdValue := range frame.FlagIdValues {
    76  		flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id)
    77  		if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
    78  			return
    79  		}
    80  		if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
    81  			return
    82  		}
    83  	}
    84  	return
    85  }
    86  
    87  func (frame *PingFrame) write(f *Framer) (err error) {
    88  	if frame.Id == 0 {
    89  		return &Error{ZeroStreamId, 0}
    90  	}
    91  	frame.CFHeader.version = Version
    92  	frame.CFHeader.frameType = TypePing
    93  	frame.CFHeader.Flags = 0
    94  	frame.CFHeader.length = 4
    95  
    96  	// Serialize frame to Writer.
    97  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
    98  		return
    99  	}
   100  	if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
   101  		return
   102  	}
   103  	return
   104  }
   105  
   106  func (frame *GoAwayFrame) write(f *Framer) (err error) {
   107  	frame.CFHeader.version = Version
   108  	frame.CFHeader.frameType = TypeGoAway
   109  	frame.CFHeader.Flags = 0
   110  	frame.CFHeader.length = 8
   111  
   112  	// Serialize frame to Writer.
   113  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
   114  		return
   115  	}
   116  	if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
   117  		return
   118  	}
   119  	if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
   120  		return
   121  	}
   122  	return nil
   123  }
   124  
   125  func (frame *HeadersFrame) write(f *Framer) error {
   126  	return f.writeHeadersFrame(frame)
   127  }
   128  
   129  func (frame *WindowUpdateFrame) write(f *Framer) (err error) {
   130  	frame.CFHeader.version = Version
   131  	frame.CFHeader.frameType = TypeWindowUpdate
   132  	frame.CFHeader.Flags = 0
   133  	frame.CFHeader.length = 8
   134  
   135  	// Serialize frame to Writer.
   136  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
   137  		return
   138  	}
   139  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
   140  		return
   141  	}
   142  	if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil {
   143  		return
   144  	}
   145  	return nil
   146  }
   147  
   148  func (frame *DataFrame) write(f *Framer) error {
   149  	return f.writeDataFrame(frame)
   150  }
   151  
   152  // WriteFrame writes a frame.
   153  func (f *Framer) WriteFrame(frame Frame) error {
   154  	return frame.write(f)
   155  }
   156  
   157  func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
   158  	if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
   159  		return err
   160  	}
   161  	if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
   162  		return err
   163  	}
   164  	flagsAndLength := uint32(h.Flags)<<24 | h.length
   165  	if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
   166  		return err
   167  	}
   168  	return nil
   169  }
   170  
   171  func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
   172  	n = 0
   173  	if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
   174  		return
   175  	}
   176  	n += 2
   177  	for name, values := range h {
   178  		if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
   179  			return
   180  		}
   181  		n += 2
   182  		name = strings.ToLower(name)
   183  		if _, err = io.WriteString(w, name); err != nil {
   184  			return
   185  		}
   186  		n += len(name)
   187  		v := strings.Join(values, headerValueSeparator)
   188  		if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
   189  			return
   190  		}
   191  		n += 2
   192  		if _, err = io.WriteString(w, v); err != nil {
   193  			return
   194  		}
   195  		n += len(v)
   196  	}
   197  	return
   198  }
   199  
   200  func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
   201  	if frame.StreamId == 0 {
   202  		return &Error{ZeroStreamId, 0}
   203  	}
   204  	// Marshal the headers.
   205  	var writer io.Writer = f.headerBuf
   206  	if !f.headerCompressionDisabled {
   207  		writer = f.headerCompressor
   208  	}
   209  	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
   210  		return
   211  	}
   212  	if !f.headerCompressionDisabled {
   213  		f.headerCompressor.Flush()
   214  	}
   215  
   216  	// Set ControlFrameHeader.
   217  	frame.CFHeader.version = Version
   218  	frame.CFHeader.frameType = TypeSynStream
   219  	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
   220  
   221  	// Serialize frame to Writer.
   222  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
   223  		return err
   224  	}
   225  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
   226  		return err
   227  	}
   228  	if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
   229  		return err
   230  	}
   231  	if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil {
   232  		return err
   233  	}
   234  	if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil {
   235  		return err
   236  	}
   237  	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
   238  		return err
   239  	}
   240  	f.headerBuf.Reset()
   241  	return nil
   242  }
   243  
   244  func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
   245  	if frame.StreamId == 0 {
   246  		return &Error{ZeroStreamId, 0}
   247  	}
   248  	// Marshal the headers.
   249  	var writer io.Writer = f.headerBuf
   250  	if !f.headerCompressionDisabled {
   251  		writer = f.headerCompressor
   252  	}
   253  	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
   254  		return
   255  	}
   256  	if !f.headerCompressionDisabled {
   257  		f.headerCompressor.Flush()
   258  	}
   259  
   260  	// Set ControlFrameHeader.
   261  	frame.CFHeader.version = Version
   262  	frame.CFHeader.frameType = TypeSynReply
   263  	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
   264  
   265  	// Serialize frame to Writer.
   266  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
   267  		return
   268  	}
   269  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
   270  		return
   271  	}
   272  	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
   273  		return
   274  	}
   275  	f.headerBuf.Reset()
   276  	return
   277  }
   278  
   279  func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
   280  	if frame.StreamId == 0 {
   281  		return &Error{ZeroStreamId, 0}
   282  	}
   283  	// Marshal the headers.
   284  	var writer io.Writer = f.headerBuf
   285  	if !f.headerCompressionDisabled {
   286  		writer = f.headerCompressor
   287  	}
   288  	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
   289  		return
   290  	}
   291  	if !f.headerCompressionDisabled {
   292  		f.headerCompressor.Flush()
   293  	}
   294  
   295  	// Set ControlFrameHeader.
   296  	frame.CFHeader.version = Version
   297  	frame.CFHeader.frameType = TypeHeaders
   298  	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
   299  
   300  	// Serialize frame to Writer.
   301  	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
   302  		return
   303  	}
   304  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
   305  		return
   306  	}
   307  	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
   308  		return
   309  	}
   310  	f.headerBuf.Reset()
   311  	return
   312  }
   313  
   314  func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
   315  	if frame.StreamId == 0 {
   316  		return &Error{ZeroStreamId, 0}
   317  	}
   318  	if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength {
   319  		return &Error{InvalidDataFrame, frame.StreamId}
   320  	}
   321  
   322  	// Serialize frame to Writer.
   323  	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
   324  		return
   325  	}
   326  	flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
   327  	if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
   328  		return
   329  	}
   330  	if _, err = f.w.Write(frame.Data); err != nil {
   331  		return
   332  	}
   333  	return nil
   334  }
   335  

View as plain text