mux.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 // import "go.gridfinity.dev/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(Config *Config) error {
  47. if !(Config.Version == 1 || Config.Version == 2) {
  48. return errors.New("unsupported protocol version")
  49. }
  50. if !Config.KeepAliveDisabled {
  51. if Config.KeepAliveInterval == 0 {
  52. return errors.New("keep-alive interval must be positive")
  53. }
  54. if Config.KeepAliveTimeout < Config.KeepAliveInterval {
  55. return fmt.Errorf("keep-alive timeout must be larger than keep-alive interval")
  56. }
  57. }
  58. if Config.MaxFrameSize <= 0 {
  59. return errors.New("max frame size must be positive")
  60. }
  61. if Config.MaxFrameSize > 65535 {
  62. return errors.New("max frame size must not be larger than 65535")
  63. }
  64. if Config.MaxReceiveBuffer <= 0 {
  65. return errors.New("max receive buffer must be positive")
  66. }
  67. if Config.MaxStreamBuffer <= 0 {
  68. return errors.New("max stream buffer must be positive")
  69. }
  70. if Config.MaxStreamBuffer > Config.MaxReceiveBuffer {
  71. return errors.New("max stream buffer must not be larger than max receive buffer")
  72. }
  73. if Config.MaxStreamBuffer > math.MaxInt32 {
  74. return errors.New("max stream buffer cannot be larger than 2147483647")
  75. }
  76. return nil
  77. }
  78. // Server is used to initialize a new server-side Connection.
  79. func Server(Conn io.ReadWriteCloser, Config *Config) (*Session, error) {
  80. if Config == nil {
  81. Config = DefaultConfig()
  82. }
  83. if err := VerifyConfig(Config); err != nil {
  84. return nil, err
  85. }
  86. return newSession(Config, Conn, false), nil
  87. }
  88. // Client is used to initialize a new client-side Connection.
  89. func Client(Conn io.ReadWriteCloser, Config *Config) (*Session, error) {
  90. if Config == nil {
  91. Config = DefaultConfig()
  92. }
  93. if err := VerifyConfig(Config); err != nil {
  94. return nil, err
  95. }
  96. return newSession(Config, Conn, true), nil
  97. }