package websocket import ( "net/http" "strconv" "time" "github.com/kataras/iris/context" "github.com/iris-contrib/go.uuid" ) const ( // DefaultWebsocketWriteTimeout 0, no timeout DefaultWebsocketWriteTimeout = 0 // DefaultWebsocketReadTimeout 0, no timeout DefaultWebsocketReadTimeout = 0 // DefaultWebsocketPingPeriod is 0 but // could be 10 * time.Second. DefaultWebsocketPingPeriod = 0 // DefaultWebsocketMaxMessageSize 0 DefaultWebsocketMaxMessageSize = 0 // DefaultWebsocketReadBufferSize 0 DefaultWebsocketReadBufferSize = 0 // DefaultWebsocketWriterBufferSize 0 DefaultWebsocketWriterBufferSize = 0 // DefaultEvtMessageKey is the default prefix of the underline websocket events // that are being established under the hoods. // // Defaults to "iris-websocket-message:". // Last character of the prefix should be ':'. DefaultEvtMessageKey = "iris-websocket-message:" ) var ( // DefaultIDGenerator returns a random unique string for a new connection. // Used when config.IDGenerator is nil. DefaultIDGenerator = func(context.Context) string { id, err := uuid.NewV4() if err != nil { return strconv.FormatInt(time.Now().Unix(), 10) } return id.String() } ) // Config contains the websocket server's configuration, optional. type Config struct { // IDGenerator used to create (and later on, set) // an ID for each incoming websocket connections (clients). // The request is an input parameter which you can use to generate the ID (from headers for example). // If empty then the ID is generated by DefaultIDGenerator: randomString(64) IDGenerator func(ctx context.Context) string // EvtMessagePrefix is the prefix of the underline websocket events that are being established under the hoods. // This prefix is visible only to the javascript side (code) and it has nothing to do // with the message that the end-user receives. // Do not change it unless it is absolutely necessary. // // If empty then defaults to []byte("iris-websocket-message:"). EvtMessagePrefix []byte // Error is the function that will be fired if any client couldn't upgrade the HTTP connection // to a websocket connection, a handshake error. Error func(w http.ResponseWriter, r *http.Request, status int, reason error) // CheckOrigin a function that is called right before the handshake, // if returns false then that client is not allowed to connect with the websocket server. CheckOrigin func(r *http.Request) bool // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration // WriteTimeout time allowed to write a message to the connection. // 0 means no timeout. // Default value is 0 WriteTimeout time.Duration // ReadTimeout time allowed to read a message from the connection. // 0 means no timeout. // Default value is 0 ReadTimeout time.Duration // PingPeriod send ping messages to the connection repeatedly after this period. // The value should be close to the ReadTimeout to avoid issues. // Default value is 0. PingPeriod time.Duration // MaxMessageSize max message size allowed from connection. // Default value is 1024 MaxMessageSize int64 // BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text // compatible if you wanna use the Connection's EmitMessage to send a custom binary data to the client, like a native server-client communication. // Default value is false BinaryMessages bool // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer // size is zero, then buffers allocated by the HTTP server are used. The // I/O buffer sizes do not limit the size of the messages that can be sent // or received. // // Default value is 0. ReadBufferSize, WriteBufferSize int // EnableCompression specify if the server should attempt to negotiate per // message compression (RFC 7692). Setting this value to true does not // guarantee that compression will be supported. Currently only "no context // takeover" modes are supported. // // Defaults to false and it should be remain as it is, unless special requirements. EnableCompression bool // Subprotocols specifies the server's supported protocols in order of // preference. If this field is set, then the Upgrade method negotiates a // subprotocol by selecting the first match in this list with a protocol // requested by the client. Subprotocols []string } // Validate validates the configuration func (c Config) Validate() Config { // 0 means no timeout. if c.WriteTimeout < 0 { c.WriteTimeout = DefaultWebsocketWriteTimeout } if c.ReadTimeout < 0 { c.ReadTimeout = DefaultWebsocketReadTimeout } if c.PingPeriod <= 0 { c.PingPeriod = DefaultWebsocketPingPeriod } if c.MaxMessageSize <= 0 { c.MaxMessageSize = DefaultWebsocketMaxMessageSize } if c.ReadBufferSize <= 0 { c.ReadBufferSize = DefaultWebsocketReadBufferSize } if c.WriteBufferSize <= 0 { c.WriteBufferSize = DefaultWebsocketWriterBufferSize } if c.Error == nil { c.Error = func(w http.ResponseWriter, r *http.Request, status int, reason error) { //empty } } if c.CheckOrigin == nil { c.CheckOrigin = func(r *http.Request) bool { // allow all connections by default return true } } if len(c.EvtMessagePrefix) == 0 { c.EvtMessagePrefix = []byte(DefaultEvtMessageKey) } if c.IDGenerator == nil { c.IDGenerator = DefaultIDGenerator } return c }