mux.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Package gfsmux is a multiplexing library for Golang.
  2. //
  3. // It relies on an underlying connection to provide reliability and ordering,
  4. // such as GFCP, and provides stream-oriented multiplexing over a single channel.
  5. package gfsmux
  6. import (
  7. "errors"
  8. "fmt"
  9. "io"
  10. "math"
  11. "time"
  12. )
  13. // Config is used to tune the Smux session
  14. type Config struct {
  15. // SMUX Protocol version, support 1,2
  16. Version int
  17. // Disabled keepalive
  18. KeepAliveDisabled bool
  19. // KeepAliveInterval is how often to send a NOP command to the remote
  20. KeepAliveInterval time.Duration
  21. // KeepAliveTimeout is how long the session
  22. // will be closed if no data has arrived
  23. KeepAliveTimeout time.Duration
  24. // MaxFrameSize is used to control the maximum
  25. // frame size to sent to the remote
  26. MaxFrameSize int
  27. // MaxReceiveBuffer is used to control the maximum
  28. // number of data in the buffer pool
  29. MaxReceiveBuffer int
  30. // MaxStreamBuffer is used to control the maximum
  31. // number of data per stream
  32. MaxStreamBuffer int
  33. }
  34. // DefaultConfig is used to return a default Configuration
  35. func DefaultConfig() *Config {
  36. return &Config{
  37. Version: 1,
  38. KeepAliveInterval: 10 * time.Second,
  39. KeepAliveTimeout: 30 * time.Second,
  40. MaxFrameSize: 32768,
  41. MaxReceiveBuffer: 4194304,
  42. MaxStreamBuffer: 65536,
  43. }
  44. }
  45. // VerifyConfig is used to verify the sanity of Configuration
  46. func VerifyConfig(
  47. Config *Config,
  48. ) error {
  49. if !(Config.Version == 1 || Config.Version == 2) {
  50. return errors.New(
  51. "unsupported protocol version",
  52. )
  53. }
  54. if !Config.KeepAliveDisabled {
  55. if Config.KeepAliveInterval == 0 {
  56. return errors.New(
  57. "keep-alive interval must be positive",
  58. )
  59. }
  60. if Config.KeepAliveTimeout < Config.KeepAliveInterval {
  61. return fmt.Errorf(
  62. "keep-alive timeout must be larger than keep-alive interval",
  63. )
  64. }
  65. }
  66. if Config.MaxFrameSize <= 0 {
  67. return errors.New(
  68. "max frame size must be positive",
  69. )
  70. }
  71. if Config.MaxFrameSize > 65535 {
  72. return errors.New(
  73. "max frame size must not be larger than 65535",
  74. )
  75. }
  76. if Config.MaxReceiveBuffer <= 0 {
  77. return errors.New(
  78. "max receive buffer must be positive",
  79. )
  80. }
  81. if Config.MaxStreamBuffer <= 0 {
  82. return errors.New(
  83. "max stream buffer must be positive",
  84. )
  85. }
  86. if Config.MaxStreamBuffer > Config.MaxReceiveBuffer {
  87. return errors.New(
  88. "max stream buffer must not be larger than max receive buffer",
  89. )
  90. }
  91. if Config.MaxStreamBuffer > math.MaxInt32 {
  92. return errors.New(
  93. "max stream buffer cannot be larger than 2147483647",
  94. )
  95. }
  96. return nil
  97. }
  98. // Server is used to initialize a new server-side Connection.
  99. func Server(
  100. Conn io.ReadWriteCloser,
  101. Config *Config,
  102. ) (
  103. *Session,
  104. error,
  105. ) {
  106. if Config == nil {
  107. Config = DefaultConfig()
  108. }
  109. if err := VerifyConfig(
  110. Config,
  111. ); err != nil {
  112. return nil, err
  113. }
  114. return newSession(
  115. Config,
  116. Conn,
  117. false,
  118. ), nil
  119. }
  120. // Client is used to initialize a new client-side Connection.
  121. func Client(
  122. Conn io.ReadWriteCloser,
  123. Config *Config,
  124. ) (
  125. *Session,
  126. error,
  127. ) {
  128. if Config == nil {
  129. Config = DefaultConfig()
  130. }
  131. if err := VerifyConfig(
  132. Config,
  133. ); err != nil {
  134. return nil, err
  135. }
  136. return newSession(
  137. Config,
  138. Conn,
  139. true,
  140. ), nil
  141. }