// MIT License // // Copyright (c) 2016-2017 xtaci // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package smux import ( "encoding/binary" "fmt" ) const ( // cmds // protocol version 1: cmdSYN byte = iota // stream open cmdFIN // stream close, a.k.a EOF mark cmdPSH // data push cmdNOP // no operation // protocol version 2 extra commands // notify bytes consumed by remote peer-end cmdUPD ) const ( // data size of cmdUPD, format: // |4B data consumed(ACK)| 4B window size(WINDOW) | szCmdUPD = 8 ) const ( // initial peer window guess, a slow-start initialPeerWindow = 262144 ) const ( sizeOfVer = 1 sizeOfCmd = 1 sizeOfLength = 2 sizeOfSid = 4 headerSize = sizeOfVer + sizeOfCmd + sizeOfSid + sizeOfLength ) // Frame defines a packet from or to be multiplexed into a single connection type Frame struct { ver byte // version cmd byte // command sid uint32 // stream id data []byte // payload } // newFrame creates a new frame with given version, command and stream id func newFrame(version byte, cmd byte, sid uint32) Frame { return Frame{ver: version, cmd: cmd, sid: sid} } // rawHeader is a byte array representation of Frame header type rawHeader [headerSize]byte func (h rawHeader) Version() byte { return h[0] } func (h rawHeader) Cmd() byte { return h[1] } func (h rawHeader) Length() uint16 { return binary.LittleEndian.Uint16(h[2:]) } func (h rawHeader) StreamID() uint32 { return binary.LittleEndian.Uint32(h[4:]) } func (h rawHeader) String() string { return fmt.Sprintf("Version:%d Cmd:%d StreamID:%d Length:%d", h.Version(), h.Cmd(), h.StreamID(), h.Length()) } // updHeader is a byte array representation of cmdUPD type updHeader [szCmdUPD]byte func (h updHeader) Consumed() uint32 { return binary.LittleEndian.Uint32(h[:]) } func (h updHeader) Window() uint32 { return binary.LittleEndian.Uint32(h[4:]) }