mirror of https://github.com/fatedier/frp
				
				
				
			
		
			
				
	
	
		
			158 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
package yamux
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/binary"
 | 
						|
	"fmt"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// ErrInvalidVersion means we received a frame with an
 | 
						|
	// invalid version
 | 
						|
	ErrInvalidVersion = fmt.Errorf("invalid protocol version")
 | 
						|
 | 
						|
	// ErrInvalidMsgType means we received a frame with an
 | 
						|
	// invalid message type
 | 
						|
	ErrInvalidMsgType = fmt.Errorf("invalid msg type")
 | 
						|
 | 
						|
	// ErrSessionShutdown is used if there is a shutdown during
 | 
						|
	// an operation
 | 
						|
	ErrSessionShutdown = fmt.Errorf("session shutdown")
 | 
						|
 | 
						|
	// ErrStreamsExhausted is returned if we have no more
 | 
						|
	// stream ids to issue
 | 
						|
	ErrStreamsExhausted = fmt.Errorf("streams exhausted")
 | 
						|
 | 
						|
	// ErrDuplicateStream is used if a duplicate stream is
 | 
						|
	// opened inbound
 | 
						|
	ErrDuplicateStream = fmt.Errorf("duplicate stream initiated")
 | 
						|
 | 
						|
	// ErrReceiveWindowExceeded indicates the window was exceeded
 | 
						|
	ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded")
 | 
						|
 | 
						|
	// ErrTimeout is used when we reach an IO deadline
 | 
						|
	ErrTimeout = fmt.Errorf("i/o deadline reached")
 | 
						|
 | 
						|
	// ErrStreamClosed is returned when using a closed stream
 | 
						|
	ErrStreamClosed = fmt.Errorf("stream closed")
 | 
						|
 | 
						|
	// ErrUnexpectedFlag is set when we get an unexpected flag
 | 
						|
	ErrUnexpectedFlag = fmt.Errorf("unexpected flag")
 | 
						|
 | 
						|
	// ErrRemoteGoAway is used when we get a go away from the other side
 | 
						|
	ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections")
 | 
						|
 | 
						|
	// ErrConnectionReset is sent if a stream is reset. This can happen
 | 
						|
	// if the backlog is exceeded, or if there was a remote GoAway.
 | 
						|
	ErrConnectionReset = fmt.Errorf("connection reset")
 | 
						|
 | 
						|
	// ErrConnectionWriteTimeout indicates that we hit the "safety valve"
 | 
						|
	// timeout writing to the underlying stream connection.
 | 
						|
	ErrConnectionWriteTimeout = fmt.Errorf("connection write timeout")
 | 
						|
 | 
						|
	// ErrKeepAliveTimeout is sent if a missed keepalive caused the stream close
 | 
						|
	ErrKeepAliveTimeout = fmt.Errorf("keepalive timeout")
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// protoVersion is the only version we support
 | 
						|
	protoVersion uint8 = 0
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// Data is used for data frames. They are followed
 | 
						|
	// by length bytes worth of payload.
 | 
						|
	typeData uint8 = iota
 | 
						|
 | 
						|
	// WindowUpdate is used to change the window of
 | 
						|
	// a given stream. The length indicates the delta
 | 
						|
	// update to the window.
 | 
						|
	typeWindowUpdate
 | 
						|
 | 
						|
	// Ping is sent as a keep-alive or to measure
 | 
						|
	// the RTT. The StreamID and Length value are echoed
 | 
						|
	// back in the response.
 | 
						|
	typePing
 | 
						|
 | 
						|
	// GoAway is sent to terminate a session. The StreamID
 | 
						|
	// should be 0 and the length is an error code.
 | 
						|
	typeGoAway
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// SYN is sent to signal a new stream. May
 | 
						|
	// be sent with a data payload
 | 
						|
	flagSYN uint16 = 1 << iota
 | 
						|
 | 
						|
	// ACK is sent to acknowledge a new stream. May
 | 
						|
	// be sent with a data payload
 | 
						|
	flagACK
 | 
						|
 | 
						|
	// FIN is sent to half-close the given stream.
 | 
						|
	// May be sent with a data payload.
 | 
						|
	flagFIN
 | 
						|
 | 
						|
	// RST is used to hard close a given stream.
 | 
						|
	flagRST
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// initialStreamWindow is the initial stream window size
 | 
						|
	initialStreamWindow uint32 = 256 * 1024
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// goAwayNormal is sent on a normal termination
 | 
						|
	goAwayNormal uint32 = iota
 | 
						|
 | 
						|
	// goAwayProtoErr sent on a protocol error
 | 
						|
	goAwayProtoErr
 | 
						|
 | 
						|
	// goAwayInternalErr sent on an internal error
 | 
						|
	goAwayInternalErr
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	sizeOfVersion  = 1
 | 
						|
	sizeOfType     = 1
 | 
						|
	sizeOfFlags    = 2
 | 
						|
	sizeOfStreamID = 4
 | 
						|
	sizeOfLength   = 4
 | 
						|
	headerSize     = sizeOfVersion + sizeOfType + sizeOfFlags +
 | 
						|
		sizeOfStreamID + sizeOfLength
 | 
						|
)
 | 
						|
 | 
						|
type header []byte
 | 
						|
 | 
						|
func (h header) Version() uint8 {
 | 
						|
	return h[0]
 | 
						|
}
 | 
						|
 | 
						|
func (h header) MsgType() uint8 {
 | 
						|
	return h[1]
 | 
						|
}
 | 
						|
 | 
						|
func (h header) Flags() uint16 {
 | 
						|
	return binary.BigEndian.Uint16(h[2:4])
 | 
						|
}
 | 
						|
 | 
						|
func (h header) StreamID() uint32 {
 | 
						|
	return binary.BigEndian.Uint32(h[4:8])
 | 
						|
}
 | 
						|
 | 
						|
func (h header) Length() uint32 {
 | 
						|
	return binary.BigEndian.Uint32(h[8:12])
 | 
						|
}
 | 
						|
 | 
						|
func (h header) String() string {
 | 
						|
	return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d",
 | 
						|
		h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length())
 | 
						|
}
 | 
						|
 | 
						|
func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) {
 | 
						|
	h[0] = protoVersion
 | 
						|
	h[1] = msgType
 | 
						|
	binary.BigEndian.PutUint16(h[2:4], flags)
 | 
						|
	binary.BigEndian.PutUint32(h[4:8], streamID)
 | 
						|
	binary.BigEndian.PutUint32(h[8:12], length)
 | 
						|
}
 |