| package yamux |
| |
| import ( |
| "fmt" |
| "io" |
| "os" |
| "time" |
| ) |
| |
| // Config is used to tune the Yamux session |
| type Config struct { |
| // AcceptBacklog is used to limit how many streams may be |
| // waiting an accept. |
| AcceptBacklog int |
| |
| // EnableKeepalive is used to do a period keep alive |
| // messages using a ping. |
| EnableKeepAlive bool |
| |
| // KeepAliveInterval is how often to perform the keep alive |
| KeepAliveInterval time.Duration |
| |
| // ConnectionWriteTimeout is meant to be a "safety valve" timeout after |
| // we which will suspect a problem with the underlying connection and |
| // close it. This is only applied to writes, where's there's generally |
| // an expectation that things will move along quickly. |
| ConnectionWriteTimeout time.Duration |
| |
| // MaxStreamWindowSize is used to control the maximum |
| // window size that we allow for a stream. |
| MaxStreamWindowSize uint32 |
| |
| // LogOutput is used to control the log destination |
| LogOutput io.Writer |
| } |
| |
| // DefaultConfig is used to return a default configuration |
| func DefaultConfig() *Config { |
| return &Config{ |
| AcceptBacklog: 256, |
| EnableKeepAlive: true, |
| KeepAliveInterval: 30 * time.Second, |
| ConnectionWriteTimeout: 10 * time.Second, |
| MaxStreamWindowSize: initialStreamWindow, |
| LogOutput: os.Stderr, |
| } |
| } |
| |
| // VerifyConfig is used to verify the sanity of configuration |
| func VerifyConfig(config *Config) error { |
| if config.AcceptBacklog <= 0 { |
| return fmt.Errorf("backlog must be positive") |
| } |
| if config.KeepAliveInterval == 0 { |
| return fmt.Errorf("keep-alive interval must be positive") |
| } |
| if config.MaxStreamWindowSize < initialStreamWindow { |
| return fmt.Errorf("MaxStreamWindowSize must be larger than %d", initialStreamWindow) |
| } |
| return nil |
| } |
| |
| // Server is used to initialize a new server-side connection. |
| // There must be at most one server-side connection. If a nil config is |
| // provided, the DefaultConfiguration will be used. |
| func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) { |
| if config == nil { |
| config = DefaultConfig() |
| } |
| if err := VerifyConfig(config); err != nil { |
| return nil, err |
| } |
| return newSession(config, conn, false), nil |
| } |
| |
| // Client is used to initialize a new client-side connection. |
| // There must be at most one client-side connection. |
| func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) { |
| if config == nil { |
| config = DefaultConfig() |
| } |
| |
| if err := VerifyConfig(config); err != nil { |
| return nil, err |
| } |
| return newSession(config, conn, true), nil |
| } |