2017-02-15 07:40:43 +01:00
package websocket
import (
"bytes"
2018-10-21 18:20:05 +02:00
"errors"
2017-02-15 07:40:43 +01:00
"io"
"net"
"strconv"
"sync"
"time"
"github.com/gorilla/websocket"
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
"github.com/kataras/iris/context"
2017-02-15 07:40:43 +01:00
)
2017-02-22 19:32:38 +01:00
type (
connectionValue struct {
key [ ] byte
value interface { }
}
// ConnectionValues is the temporary connection's memory store
ConnectionValues [ ] connectionValue
)
// Set sets a value based on the key
func ( r * ConnectionValues ) Set ( key string , value interface { } ) {
args := * r
n := len ( args )
for i := 0 ; i < n ; i ++ {
kv := & args [ i ]
if string ( kv . key ) == key {
kv . value = value
return
}
}
c := cap ( args )
if c > n {
args = args [ : n + 1 ]
kv := & args [ n ]
kv . key = append ( kv . key [ : 0 ] , key ... )
kv . value = value
* r = args
return
}
kv := connectionValue { }
kv . key = append ( kv . key [ : 0 ] , key ... )
kv . value = value
* r = append ( args , kv )
}
// Get returns a value based on its key
func ( r * ConnectionValues ) Get ( key string ) interface { } {
args := * r
n := len ( args )
for i := 0 ; i < n ; i ++ {
kv := & args [ i ]
if string ( kv . key ) == key {
return kv . value
}
}
return nil
}
// Reset clears the values
func ( r * ConnectionValues ) Reset ( ) {
* r = ( * r ) [ : 0 ]
}
2017-12-27 16:09:47 +01:00
// UnderlineConnection is the underline connection, nothing to think about,
// it's used internally mostly but can be used for extreme cases with other libraries.
2017-02-15 07:40:43 +01:00
type UnderlineConnection interface {
// SetWriteDeadline sets the write deadline on the underlying network
// connection. After a write has timed out, the websocket state is corrupt and
// all future writes will return an error. A zero value for t means writes will
// not time out.
SetWriteDeadline ( t time . Time ) error
// SetReadDeadline sets the read deadline on the underlying network connection.
// After a read has timed out, the websocket connection state is corrupt and
// all future reads will return an error. A zero value for t means reads will
// not time out.
SetReadDeadline ( t time . Time ) error
// SetReadLimit sets the maximum size for a message read from the peer. If a
// message exceeds the limit, the connection sends a close frame to the peer
// and returns ErrReadLimit to the application.
SetReadLimit ( limit int64 )
// SetPongHandler sets the handler for pong messages received from the peer.
// The appData argument to h is the PONG frame application data. The default
// pong handler does nothing.
SetPongHandler ( h func ( appData string ) error )
// SetPingHandler sets the handler for ping messages received from the peer.
// The appData argument to h is the PING frame application data. The default
// ping handler sends a pong to the peer.
SetPingHandler ( h func ( appData string ) error )
// WriteControl writes a control message with the given deadline. The allowed
// message types are CloseMessage, PingMessage and PongMessage.
WriteControl ( messageType int , data [ ] byte , deadline time . Time ) error
// WriteMessage is a helper method for getting a writer using NextWriter,
// writing the message and closing the writer.
WriteMessage ( messageType int , data [ ] byte ) error
// ReadMessage is a helper method for getting a reader using NextReader and
// reading from that reader to a buffer.
ReadMessage ( ) ( messageType int , p [ ] byte , err error )
// NextWriter returns a writer for the next message to send. The writer's Close
// method flushes the complete message to the network.
//
// There can be at most one open writer on a connection. NextWriter closes the
// previous writer if the application has not already done so.
NextWriter ( messageType int ) ( io . WriteCloser , error )
// Close closes the underlying network connection without sending or waiting for a close frame.
Close ( ) error
}
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
// -------------------------------Connection implementation-----------------------------
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
type (
2017-12-27 16:09:47 +01:00
// DisconnectFunc is the callback which is fired when a client/connection closed
2017-02-15 07:40:43 +01:00
DisconnectFunc func ( )
2017-12-27 16:09:47 +01:00
// LeaveRoomFunc is the callback which is fired when a client/connection leaves from any room.
2017-02-22 19:32:38 +01:00
// This is called automatically when client/connection disconnected
// (because websocket server automatically leaves from all joined rooms)
LeaveRoomFunc func ( roomName string )
2017-12-27 16:09:47 +01:00
// ErrorFunc is the callback which fires whenever an error occurs
2018-05-02 05:40:18 +02:00
ErrorFunc ( func ( error ) )
2017-02-15 07:40:43 +01:00
// NativeMessageFunc is the callback for native websocket messages, receives one []byte parameter which is the raw client's message
NativeMessageFunc func ( [ ] byte )
// MessageFunc is the second argument to the Emitter's Emit functions.
// A callback which should receives one parameter of type string, int, bool or any valid JSON/Go struct
MessageFunc interface { }
2017-12-01 23:48:37 +01:00
// PingFunc is the callback which fires each ping
PingFunc func ( )
2018-04-30 13:27:28 +02:00
// PongFunc is the callback which fires on pong message received
PongFunc func ( )
2017-02-15 07:40:43 +01:00
// Connection is the front-end API that you will use to communicate with the client side
Connection interface {
// Emitter implements EmitMessage & Emit
Emitter
2017-12-20 16:56:28 +01:00
// Err is not nil if the upgrader failed to upgrade http to websocket connection.
Err ( ) error
2017-02-15 07:40:43 +01:00
// ID returns the connection's identifier
ID ( ) string
2017-07-10 17:32:42 +02:00
// Server returns the websocket server instance
// which this connection is listening to.
//
// Its connection-relative operations are safe for use.
Server ( ) * Server
2018-04-25 12:40:40 +02:00
// Write writes a raw websocket message with a specific type to the client
// used by ping messages and any CloseMessage types.
Write ( websocketMessageType int , data [ ] byte ) error
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
// Context returns the (upgraded) context.Context of this connection
2017-02-15 07:40:43 +01:00
// avoid using it, you normally don't need it,
// websocket has everything you need to authenticate the user BUT if it's necessary
// then you use it to receive user information, for example: from headers
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
Context ( ) context . Context
2017-02-15 07:40:43 +01:00
2017-12-27 16:09:47 +01:00
// OnDisconnect registers a callback which is fired when this connection is closed by an error or manual
2017-02-15 07:40:43 +01:00
OnDisconnect ( DisconnectFunc )
2017-07-10 17:32:42 +02:00
// OnError registers a callback which fires when this connection occurs an error
OnError ( ErrorFunc )
2017-12-01 23:48:37 +01:00
// OnPing registers a callback which fires on each ping
OnPing ( PingFunc )
2018-04-30 13:27:28 +02:00
// OnPong registers a callback which fires on pong message received
OnPong ( PongFunc )
2017-12-27 16:09:47 +01:00
// FireOnError can be used to send a custom error message to the connection
2017-02-15 07:40:43 +01:00
//
2017-12-27 16:09:47 +01:00
// It does nothing more than firing the OnError listeners. It doesn't send anything to the client.
2018-05-02 05:40:18 +02:00
FireOnError ( err error )
2017-12-27 16:09:47 +01:00
// To defines on what "room" (see Join) the server should send a message
// returns an Emmiter(`EmitMessage` & `Emit`) to send messages.
2017-02-15 07:40:43 +01:00
To ( string ) Emitter
// OnMessage registers a callback which fires when native websocket message received
OnMessage ( NativeMessageFunc )
2017-12-27 16:09:47 +01:00
// On registers a callback to a particular event which is fired when a message to this event is received
2017-02-15 07:40:43 +01:00
On ( string , MessageFunc )
2017-12-27 16:09:47 +01:00
// Join registers this connection to a room, if it doesn't exist then it creates a new. One room can have one or more connections. One connection can be joined to many rooms. All connections are joined to a room specified by their `ID` automatically.
2017-02-15 07:40:43 +01:00
Join ( string )
2018-02-03 17:53:39 +01:00
// IsJoined returns true when this connection is joined to the room, otherwise false.
// It Takes the room name as its input parameter.
IsJoined ( roomName string ) bool
2017-12-27 16:09:47 +01:00
// Leave removes this connection entry from a room
2017-02-22 19:32:38 +01:00
// Returns true if the connection has actually left from the particular room.
Leave ( string ) bool
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
// OnLeave registers a callback which fires when this connection left from any joined room.
2017-02-22 19:32:38 +01:00
// This callback is called automatically on Disconnected client, because websocket server automatically
// deletes the disconnected connection from any joined rooms.
//
// Note: the callback(s) called right before the server deletes the connection from the room
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
// so the connection theoretical can still send messages to its room right before it is being disconnected.
2017-02-22 19:32:38 +01:00
OnLeave ( roomLeaveCb LeaveRoomFunc )
2017-12-20 16:56:28 +01:00
// Wait starts the pinger and the messages reader,
// it's named as "Wait" because it should be called LAST,
// after the "On" events IF server's `Upgrade` is used,
// otherise you don't have to call it because the `Handler()` does it automatically.
Wait ( )
2017-02-15 07:40:43 +01:00
// Disconnect disconnects the client, close the underline websocket conn and removes it from the conn list
// returns the error, if any, from the underline connection
Disconnect ( ) error
2017-02-25 19:25:22 +01:00
// SetValue sets a key-value pair on the connection's mem store.
SetValue ( key string , value interface { } )
// GetValue gets a value by its key from the connection's mem store.
GetValue ( key string ) interface { }
// GetValueArrString gets a value as []string by its key from the connection's mem store.
GetValueArrString ( key string ) [ ] string
// GetValueString gets a value as string by its key from the connection's mem store.
GetValueString ( key string ) string
// GetValueInt gets a value as integer by its key from the connection's mem store.
GetValueInt ( key string ) int
2017-02-15 07:40:43 +01:00
}
connection struct {
2017-12-20 16:56:28 +01:00
err error
2017-02-15 07:40:43 +01:00
underline UnderlineConnection
id string
messageType int
disconnected bool
onDisconnectListeners [ ] DisconnectFunc
2017-02-22 19:32:38 +01:00
onRoomLeaveListeners [ ] LeaveRoomFunc
2017-02-15 07:40:43 +01:00
onErrorListeners [ ] ErrorFunc
2017-12-01 23:48:37 +01:00
onPingListeners [ ] PingFunc
2018-04-30 13:27:28 +02:00
onPongListeners [ ] PongFunc
2017-02-15 07:40:43 +01:00
onNativeMessageListeners [ ] NativeMessageFunc
onEventListeners map [ string ] [ ] MessageFunc
2017-12-20 16:56:28 +01:00
started bool
2017-02-15 07:40:43 +01:00
// these were maden for performance only
self Emitter // pre-defined emitter than sends message to its self client
broadcast Emitter // pre-defined emitter that sends message to all except this
all Emitter // pre-defined emitter which sends message to all clients
2018-11-06 03:06:50 +01:00
// access to the Context, use with caution, you can't use response writer as you imagine.
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
ctx context . Context
2017-02-22 19:32:38 +01:00
values ConnectionValues
2017-07-10 17:32:42 +02:00
server * Server
2017-02-15 07:40:43 +01:00
// #119 , websocket writers are not protected by locks inside the gorilla's websocket code
// so we must protect them otherwise we're getting concurrent connection error on multi writers in the same time.
writerMu sync . Mutex
// same exists for reader look here: https://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages
// but we only use one reader in one goroutine, so we are safe.
// readerMu sync.Mutex
}
)
var _ Connection = & connection { }
2018-05-02 05:40:18 +02:00
// CloseMessage denotes a close control message. The optional message
// payload contains a numeric code and text. Use the FormatCloseMessage
// function to format a close message payload.
//
// Use the `Connection#Disconnect` instead.
2018-04-25 12:40:40 +02:00
const CloseMessage = websocket . CloseMessage
2017-07-10 17:32:42 +02:00
func newConnection ( ctx context . Context , s * Server , underlineConn UnderlineConnection , id string ) * connection {
2017-02-15 07:40:43 +01:00
c := & connection {
underline : underlineConn ,
id : id ,
messageType : websocket . TextMessage ,
onDisconnectListeners : make ( [ ] DisconnectFunc , 0 ) ,
2017-02-22 19:32:38 +01:00
onRoomLeaveListeners : make ( [ ] LeaveRoomFunc , 0 ) ,
2017-02-15 07:40:43 +01:00
onErrorListeners : make ( [ ] ErrorFunc , 0 ) ,
onNativeMessageListeners : make ( [ ] NativeMessageFunc , 0 ) ,
onEventListeners : make ( map [ string ] [ ] MessageFunc , 0 ) ,
2018-04-30 13:27:28 +02:00
onPongListeners : make ( [ ] PongFunc , 0 ) ,
2017-12-20 16:56:28 +01:00
started : false ,
2017-02-15 07:40:43 +01:00
ctx : ctx ,
server : s ,
}
if s . config . BinaryMessages {
c . messageType = websocket . BinaryMessage
}
c . self = newEmitter ( c , c . id )
c . broadcast = newEmitter ( c , Broadcast )
c . all = newEmitter ( c , All )
return c
}
2017-12-20 16:56:28 +01:00
// Err is not nil if the upgrader failed to upgrade http to websocket connection.
func ( c * connection ) Err ( ) error {
return c . err
}
2018-04-25 12:40:40 +02:00
// Write writes a raw websocket message with a specific type to the client
2017-02-15 07:40:43 +01:00
// used by ping messages and any CloseMessage types.
2018-04-25 12:40:40 +02:00
func ( c * connection ) Write ( websocketMessageType int , data [ ] byte ) error {
2017-02-15 07:40:43 +01:00
// for any-case the app tries to write from different goroutines,
// we must protect them because they're reporting that as bug...
c . writerMu . Lock ( )
if writeTimeout := c . server . config . WriteTimeout ; writeTimeout > 0 {
// set the write deadline based on the configuration
c . underline . SetWriteDeadline ( time . Now ( ) . Add ( writeTimeout ) )
}
// .WriteMessage same as NextWriter and close (flush)
err := c . underline . WriteMessage ( websocketMessageType , data )
c . writerMu . Unlock ( )
if err != nil {
// if failed then the connection is off, fire the disconnect
c . Disconnect ( )
}
2017-10-17 00:54:17 +02:00
return err
2017-02-15 07:40:43 +01:00
}
// writeDefault is the same as write but the message type is the configured by c.messageType
// if BinaryMessages is enabled then it's raw []byte as you expected to work with protobufs
func ( c * connection ) writeDefault ( data [ ] byte ) {
2018-04-25 12:40:40 +02:00
c . Write ( c . messageType , data )
2017-02-15 07:40:43 +01:00
}
const (
// WriteWait is 1 second at the internal implementation,
// same as here but this can be changed at the future*
WriteWait = 1 * time . Second
)
func ( c * connection ) startPinger ( ) {
// this is the default internal handler, we just change the writeWait because of the actions we must do before
// the server sends the ping-pong.
pingHandler := func ( message string ) error {
err := c . underline . WriteControl ( websocket . PongMessage , [ ] byte ( message ) , time . Now ( ) . Add ( WriteWait ) )
if err == websocket . ErrCloseSent {
return nil
} else if e , ok := err . ( net . Error ) ; ok && e . Temporary ( ) {
return nil
}
return err
}
c . underline . SetPingHandler ( pingHandler )
go func ( ) {
for {
2017-10-20 05:06:31 +02:00
// using sleep avoids the ticker error that causes a memory leak
time . Sleep ( c . server . config . PingPeriod )
if c . disconnected {
// verifies if already disconected
break
}
2017-12-01 23:48:37 +01:00
//fire all OnPing methods
c . fireOnPing ( )
2017-02-15 07:40:43 +01:00
// try to ping the client, if failed then it disconnects
2018-04-25 12:40:40 +02:00
err := c . Write ( websocket . PingMessage , [ ] byte { } )
2017-10-20 05:06:31 +02:00
if err != nil {
// must stop to exit the loop and finish the go routine
2017-10-17 00:54:17 +02:00
break
}
2017-02-15 07:40:43 +01:00
}
} ( )
}
2017-12-20 16:56:28 +01:00
func ( c * connection ) fireOnPing ( ) {
// fire the onPingListeners
for i := range c . onPingListeners {
c . onPingListeners [ i ] ( )
}
}
2018-04-30 13:27:28 +02:00
func ( c * connection ) fireOnPong ( ) {
// fire the onPongListeners
for i := range c . onPongListeners {
c . onPongListeners [ i ] ( )
}
}
2017-02-15 07:40:43 +01:00
func ( c * connection ) startReader ( ) {
conn := c . underline
hasReadTimeout := c . server . config . ReadTimeout > 0
conn . SetReadLimit ( c . server . config . MaxMessageSize )
conn . SetPongHandler ( func ( s string ) error {
if hasReadTimeout {
conn . SetReadDeadline ( time . Now ( ) . Add ( c . server . config . ReadTimeout ) )
}
2018-04-30 13:27:28 +02:00
//fire all OnPong methods
go c . fireOnPong ( )
2017-02-15 07:40:43 +01:00
return nil
} )
defer func ( ) {
c . Disconnect ( )
} ( )
for {
if hasReadTimeout {
// set the read deadline based on the configuration
conn . SetReadDeadline ( time . Now ( ) . Add ( c . server . config . ReadTimeout ) )
}
_ , data , err := conn . ReadMessage ( )
if err != nil {
if websocket . IsUnexpectedCloseError ( err , websocket . CloseGoingAway ) {
2018-05-02 05:40:18 +02:00
c . FireOnError ( err )
2017-02-15 07:40:43 +01:00
}
break
} else {
c . messageReceived ( data )
}
}
}
// messageReceived checks the incoming message and fire the nativeMessage listeners or the event listeners (ws custom message)
func ( c * connection ) messageReceived ( data [ ] byte ) {
2018-10-28 00:19:22 +02:00
if bytes . HasPrefix ( data , c . server . config . EvtMessagePrefix ) {
2017-02-15 07:40:43 +01:00
//it's a custom ws message
2018-10-28 00:19:22 +02:00
receivedEvt := c . server . messageSerializer . getWebsocketCustomEvent ( data )
listeners , ok := c . onEventListeners [ string ( receivedEvt ) ]
if ! ok || len ( listeners ) == 0 {
return // if not listeners for this event exit from here
2017-02-15 07:40:43 +01:00
}
2018-10-28 00:19:22 +02:00
customMessage , err := c . server . messageSerializer . deserialize ( receivedEvt , data )
2017-02-15 07:40:43 +01:00
if customMessage == nil || err != nil {
return
}
for i := range listeners {
if fn , ok := listeners [ i ] . ( func ( ) ) ; ok { // its a simple func(){} callback
fn ( )
} else if fnString , ok := listeners [ i ] . ( func ( string ) ) ; ok {
if msgString , is := customMessage . ( string ) ; is {
fnString ( msgString )
} else if msgInt , is := customMessage . ( int ) ; is {
// here if server side waiting for string but client side sent an int, just convert this int to a string
fnString ( strconv . Itoa ( msgInt ) )
}
} else if fnInt , ok := listeners [ i ] . ( func ( int ) ) ; ok {
fnInt ( customMessage . ( int ) )
} else if fnBool , ok := listeners [ i ] . ( func ( bool ) ) ; ok {
fnBool ( customMessage . ( bool ) )
} else if fnBytes , ok := listeners [ i ] . ( func ( [ ] byte ) ) ; ok {
fnBytes ( customMessage . ( [ ] byte ) )
} else {
listeners [ i ] . ( func ( interface { } ) ) ( customMessage )
}
}
} else {
// it's native websocket message
for i := range c . onNativeMessageListeners {
c . onNativeMessageListeners [ i ] ( data )
}
}
}
func ( c * connection ) ID ( ) string {
return c . id
}
2017-07-10 17:32:42 +02:00
func ( c * connection ) Server ( ) * Server {
return c . server
}
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
func ( c * connection ) Context ( ) context . Context {
2017-02-15 07:40:43 +01:00
return c . ctx
}
2017-02-22 19:32:38 +01:00
func ( c * connection ) Values ( ) ConnectionValues {
return c . values
}
2017-02-15 07:40:43 +01:00
func ( c * connection ) fireDisconnect ( ) {
for i := range c . onDisconnectListeners {
c . onDisconnectListeners [ i ] ( )
}
}
func ( c * connection ) OnDisconnect ( cb DisconnectFunc ) {
c . onDisconnectListeners = append ( c . onDisconnectListeners , cb )
}
2017-07-10 17:32:42 +02:00
func ( c * connection ) OnError ( cb ErrorFunc ) {
2017-02-15 07:40:43 +01:00
c . onErrorListeners = append ( c . onErrorListeners , cb )
}
2017-12-01 23:48:37 +01:00
func ( c * connection ) OnPing ( cb PingFunc ) {
c . onPingListeners = append ( c . onPingListeners , cb )
}
2018-04-30 13:27:28 +02:00
func ( c * connection ) OnPong ( cb PongFunc ) {
c . onPongListeners = append ( c . onPongListeners , cb )
}
2018-05-02 05:40:18 +02:00
func ( c * connection ) FireOnError ( err error ) {
2017-02-15 07:40:43 +01:00
for _ , cb := range c . onErrorListeners {
2018-05-02 05:40:18 +02:00
cb ( err )
2017-02-15 07:40:43 +01:00
}
}
func ( c * connection ) To ( to string ) Emitter {
if to == Broadcast { // if send to all except me, then return the pre-defined emitter, and so on
return c . broadcast
} else if to == All {
return c . all
} else if to == c . id {
return c . self
}
2018-05-02 16:47:14 +02:00
2017-02-15 07:40:43 +01:00
// is an emitter to another client/connection
return newEmitter ( c , to )
}
func ( c * connection ) EmitMessage ( nativeMessage [ ] byte ) error {
return c . self . EmitMessage ( nativeMessage )
}
func ( c * connection ) Emit ( event string , message interface { } ) error {
return c . self . Emit ( event , message )
}
func ( c * connection ) OnMessage ( cb NativeMessageFunc ) {
c . onNativeMessageListeners = append ( c . onNativeMessageListeners , cb )
}
func ( c * connection ) On ( event string , cb MessageFunc ) {
if c . onEventListeners [ event ] == nil {
c . onEventListeners [ event ] = make ( [ ] MessageFunc , 0 )
}
c . onEventListeners [ event ] = append ( c . onEventListeners [ event ] , cb )
}
func ( c * connection ) Join ( roomName string ) {
c . server . Join ( roomName , c . id )
}
2018-02-03 17:53:39 +01:00
func ( c * connection ) IsJoined ( roomName string ) bool {
return c . server . IsJoined ( roomName , c . id )
}
2017-02-22 19:32:38 +01:00
func ( c * connection ) Leave ( roomName string ) bool {
return c . server . Leave ( roomName , c . id )
}
func ( c * connection ) OnLeave ( roomLeaveCb LeaveRoomFunc ) {
c . onRoomLeaveListeners = append ( c . onRoomLeaveListeners , roomLeaveCb )
// note: the callbacks are called from the server on the '.leave' and '.LeaveAll' funcs.
}
func ( c * connection ) fireOnLeave ( roomName string ) {
2017-10-11 19:34:01 +02:00
// check if connection is already closed
if c == nil {
return
}
2017-02-22 19:32:38 +01:00
// fire the onRoomLeaveListeners
for i := range c . onRoomLeaveListeners {
c . onRoomLeaveListeners [ i ] ( roomName )
}
2017-02-15 07:40:43 +01:00
}
2017-12-20 16:56:28 +01:00
// Wait starts the pinger and the messages reader,
// it's named as "Wait" because it should be called LAST,
// after the "On" events IF server's `Upgrade` is used,
// otherise you don't have to call it because the `Handler()` does it automatically.
func ( c * connection ) Wait ( ) {
if c . started {
return
2017-12-01 23:48:37 +01:00
}
2017-12-20 16:56:28 +01:00
c . started = true
// start the ping
c . startPinger ( )
// start the messages reader
c . startReader ( )
2017-12-01 23:48:37 +01:00
}
2018-10-21 18:20:05 +02:00
// ErrAlreadyDisconnected can be reported on the `Connection#Disconnect` function whenever the caller tries to close the
// connection when it is already closed by the client or the caller previously.
var ErrAlreadyDisconnected = errors . New ( "already disconnected" )
2017-02-15 07:40:43 +01:00
func ( c * connection ) Disconnect ( ) error {
2018-10-21 18:20:05 +02:00
if c == nil || c . disconnected {
return ErrAlreadyDisconnected
}
2017-02-15 07:40:43 +01:00
return c . server . Disconnect ( c . ID ( ) )
}
2017-02-25 19:25:22 +01:00
// mem per-conn store
func ( c * connection ) SetValue ( key string , value interface { } ) {
c . values . Set ( key , value )
}
func ( c * connection ) GetValue ( key string ) interface { } {
return c . values . Get ( key )
}
func ( c * connection ) GetValueArrString ( key string ) [ ] string {
if v := c . values . Get ( key ) ; v != nil {
if arrString , ok := v . ( [ ] string ) ; ok {
return arrString
}
}
return nil
}
func ( c * connection ) GetValueString ( key string ) string {
if v := c . values . Get ( key ) ; v != nil {
if s , ok := v . ( string ) ; ok {
return s
}
}
return ""
}
func ( c * connection ) GetValueInt ( key string ) int {
if v := c . values . Get ( key ) ; v != nil {
if i , ok := v . ( int ) ; ok {
return i
} else if s , ok := v . ( string ) ; ok {
if iv , err := strconv . Atoi ( s ) ; err == nil {
return iv
}
}
}
return 0
}