const.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. // Error should meet net.Error interface for timeouts for compatability
  43. // with standard library expectations, such as http servers.
  44. timeout: true,
  45. }
  46. // ErrStreamClosed is returned when using a closed stream
  47. ErrStreamClosed = fmt.Errorf("stream closed")
  48. // ErrUnexpectedFlag is set when we get an unexpected flag
  49. ErrUnexpectedFlag = fmt.Errorf("unexpected flag")
  50. // ErrRemoteGoAway is used when we get a go away from the other side
  51. ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections")
  52. // ErrConnectionReset is sent if a stream is reset. This can happen
  53. // if the backlog is exceeded, or if there was a remote GoAway.
  54. ErrConnectionReset = fmt.Errorf("connection reset")
  55. // ErrConnectionWriteTimeout indicates that we hit the "safety valve"
  56. // timeout writing to the underlying stream connection.
  57. ErrConnectionWriteTimeout = fmt.Errorf("connection write timeout")
  58. // ErrKeepAliveTimeout is sent if a missed keepalive caused the stream close
  59. ErrKeepAliveTimeout = fmt.Errorf("keepalive timeout")
  60. )
  61. const (
  62. // protoVersion is the only version we support
  63. protoVersion uint8 = 0
  64. )
  65. const (
  66. // Data is used for data frames. They are followed
  67. // by length bytes worth of payload.
  68. typeData uint8 = iota
  69. // WindowUpdate is used to change the window of
  70. // a given stream. The length indicates the delta
  71. // update to the window.
  72. typeWindowUpdate
  73. // Ping is sent as a keep-alive or to measure
  74. // the RTT. The StreamID and Length value are echoed
  75. // back in the response.
  76. typePing
  77. // GoAway is sent to terminate a session. The StreamID
  78. // should be 0 and the length is an error code.
  79. typeGoAway
  80. )
  81. const (
  82. // SYN is sent to signal a new stream. May
  83. // be sent with a data payload
  84. flagSYN uint16 = 1 << iota
  85. // ACK is sent to acknowledge a new stream. May
  86. // be sent with a data payload
  87. flagACK
  88. // FIN is sent to half-close the given stream.
  89. // May be sent with a data payload.
  90. flagFIN
  91. // RST is used to hard close a given stream.
  92. flagRST
  93. )
  94. const (
  95. // initialStreamWindow is the initial stream window size
  96. initialStreamWindow uint32 = 256 * 1024
  97. )
  98. const (
  99. // goAwayNormal is sent on a normal termination
  100. goAwayNormal uint32 = iota
  101. // goAwayProtoErr sent on a protocol error
  102. goAwayProtoErr
  103. // goAwayInternalErr sent on an internal error
  104. goAwayInternalErr
  105. )
  106. const (
  107. sizeOfVersion = 1
  108. sizeOfType = 1
  109. sizeOfFlags = 2
  110. sizeOfStreamID = 4
  111. sizeOfLength = 4
  112. headerSize = sizeOfVersion + sizeOfType + sizeOfFlags +
  113. sizeOfStreamID + sizeOfLength
  114. )
  115. type header []byte
  116. func (h header) Version() uint8 {
  117. return h[0]
  118. }
  119. func (h header) MsgType() uint8 {
  120. return h[1]
  121. }
  122. func (h header) Flags() uint16 {
  123. return binary.BigEndian.Uint16(h[2:4])
  124. }
  125. func (h header) StreamID() uint32 {
  126. return binary.BigEndian.Uint32(h[4:8])
  127. }
  128. func (h header) Length() uint32 {
  129. return binary.BigEndian.Uint32(h[8:12])
  130. }
  131. func (h header) String() string {
  132. return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d",
  133. h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length())
  134. }
  135. func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) {
  136. h[0] = protoVersion
  137. h[1] = msgType
  138. binary.BigEndian.PutUint16(h[2:4], flags)
  139. binary.BigEndian.PutUint32(h[4:8], streamID)
  140. binary.BigEndian.PutUint32(h[8:12], length)
  141. }