const.go 4.4 KB

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