const.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package yamux
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. var (
  7. // ErrInvalidVersion means we received a frame with an
  8. // invalid version
  9. ErrInvalidVersion = fmt.Errorf("invalid protocol version")
  10. // ErrInvalidMsgType means we received a frame with an
  11. // invalid message type
  12. ErrInvalidMsgType = fmt.Errorf("invalid msg type")
  13. // ErrSessionShutdown is used if there is a shutdown during
  14. // an operation
  15. ErrSessionShutdown = fmt.Errorf("session shutdown")
  16. // ErrStreamsExhausted is returned if we have no more
  17. // stream ids to issue
  18. ErrStreamsExhausted = fmt.Errorf("streams exhausted")
  19. // ErrDuplicateStream is used if a duplicate stream is
  20. // opened inbound
  21. ErrDuplicateStream = fmt.Errorf("duplicate stream initiated")
  22. // ErrMissingStream indicates a stream was named which
  23. // does not exist.
  24. ErrMissingStream = fmt.Errorf("missing stream references")
  25. // ErrReceiveWindowExceeded indicates the window was exceeded
  26. ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded")
  27. // ErrTimeout is used when we reach an IO deadline
  28. ErrTimeout = fmt.Errorf("i/o deadline reached")
  29. // ErrStreamClosed is returned when using a closed stream
  30. ErrStreamClosed = fmt.Errorf("stream closed")
  31. // ErrUnexpectedFlag is set when we get an unexpected flag
  32. ErrUnexpectedFlag = fmt.Errorf("unexpected flag")
  33. // ErrRemoteGoAway is used when we get a go away from the other side
  34. ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections")
  35. )
  36. const (
  37. // protoVersion is the only version we support
  38. protoVersion uint8 = 0
  39. )
  40. const (
  41. // Data is used for data frames. They are followed
  42. // by length bytes worth of payload.
  43. typeData uint8 = iota
  44. // WindowUpdate is used to change the window of
  45. // a given stream. The length indicates the delta
  46. // update to the window.
  47. typeWindowUpdate
  48. // Ping is sent as a keep-alive or to measure
  49. // the RTT. The StreamID and Length value are echoed
  50. // back in the response.
  51. typePing
  52. // GoAway is sent to terminate a session. The StreamID
  53. // should be 0 and the length is an error code.
  54. typeGoAway
  55. )
  56. const (
  57. // SYN is sent to signal a new stream. May
  58. // be sent with a data payload
  59. flagSYN uint16 = 1 << iota
  60. // ACK is sent to acknowledge a new stream. May
  61. // be sent with a data payload
  62. flagACK
  63. // FIN is sent to half-close the given stream.
  64. // May be sent with a data payload.
  65. flagFIN
  66. // RST is used to hard close a given stream.
  67. flagRST
  68. )
  69. const (
  70. // initialStreamWindow is the initial stream window size
  71. initialStreamWindow uint32 = 256 * 1024
  72. )
  73. const (
  74. // goAwayNormal is sent on a normal termination
  75. goAwayNormal uint32 = iota
  76. // goAwayProtoErr sent on a protocol error
  77. goAwayProtoErr
  78. // goAwayInternalErr sent on an internal error
  79. goAwayInternalErr
  80. )
  81. const (
  82. sizeOfVersion = 1
  83. sizeOfType = 1
  84. sizeOfFlags = 2
  85. sizeOfStreamID = 4
  86. sizeOfLength = 4
  87. headerSize = sizeOfVersion + sizeOfType + sizeOfFlags +
  88. sizeOfStreamID + sizeOfLength
  89. )
  90. type header []byte
  91. func (h header) Version() uint8 {
  92. return h[0]
  93. }
  94. func (h header) MsgType() uint8 {
  95. return h[1]
  96. }
  97. func (h header) Flags() uint16 {
  98. return binary.BigEndian.Uint16(h[2:4])
  99. }
  100. func (h header) StreamID() uint32 {
  101. return binary.BigEndian.Uint32(h[4:8])
  102. }
  103. func (h header) Length() uint32 {
  104. return binary.BigEndian.Uint32(h[8:12])
  105. }
  106. func (h header) String() string {
  107. return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d",
  108. h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length())
  109. }
  110. func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) {
  111. h[0] = protoVersion
  112. h[1] = msgType
  113. binary.BigEndian.PutUint16(h[2:4], flags)
  114. binary.BigEndian.PutUint32(h[4:8], streamID)
  115. binary.BigEndian.PutUint32(h[8:12], length)
  116. }