Documentation ¶
Index ¶
- Constants
- Variables
- func DebugEach(mapOrSlice interface{}, onDebugVisitor interface{})
- func Debugf(format string, args ...interface{})
- func EnableDebug(printer interface{})
- func Exclude(connID string) fmt.Stringer
- func IsCloseError(err error) bool
- func IsDisconnectError(err error) bool
- func IsSystemEvent(event string) bool
- func IsTimeoutError(err error) bool
- func IsTryingToReconnect(err error) (ok bool)
- func Marshal(v interface{}) []byte
- func RegisterKnownError(err error)
- func Reply(body []byte) error
- type Client
- type CloseError
- type Conn
- func (c *Conn) Ask(ctx context.Context, msg Message) (Message, error)
- func (c *Conn) Close()
- func (c *Conn) Connect(ctx context.Context, namespace string) (*NSConn, error)
- func (c *Conn) Decrement(key string) int
- func (c *Conn) DeserializeMessage(msgTyp MessageType, payload []byte) Message
- func (c *Conn) DisconnectAll(ctx context.Context) error
- func (c *Conn) Get(key string) interface{}
- func (c *Conn) GetConnectedNamespaceNames() []string
- func (c *Conn) GetServerConnID() string
- func (c *Conn) HandlePayload(msgTyp MessageType, payload []byte) error
- func (c *Conn) ID() string
- func (c *Conn) Increment(key string) int
- func (c *Conn) Is(connID string) bool
- func (c *Conn) IsClient() bool
- func (c *Conn) IsClosed() bool
- func (c *Conn) Namespace(namespace string) *NSConn
- func (c *Conn) Server() *Server
- func (c *Conn) Set(key string, value interface{})
- func (c *Conn) Socket() Socket
- func (c *Conn) String() string
- func (c *Conn) WaitConnect(ctx context.Context, namespace string) (ns *NSConn, err error)
- func (c *Conn) WasReconnected() bool
- func (c *Conn) Write(msg Message) bool
- type ConnHandler
- type Dialer
- type EventMatcherFunc
- type Events
- type IDGenerator
- type Message
- type MessageHandlerFunc
- type MessageObjectMarshaler
- type MessageObjectUnmarshaler
- type MessageType
- type NSConn
- func (ns *NSConn) Ask(ctx context.Context, event string, body []byte) (Message, error)
- func (ns *NSConn) Disconnect(ctx context.Context) error
- func (ns *NSConn) Emit(event string, body []byte) bool
- func (ns *NSConn) EmitBinary(event string, body []byte) bool
- func (ns *NSConn) JoinRoom(ctx context.Context, roomName string) (*Room, error)
- func (ns *NSConn) LeaveAll(ctx context.Context) error
- func (ns *NSConn) Room(roomName string) *Room
- func (ns *NSConn) Rooms() []*Room
- func (ns *NSConn) String() string
- type Namespaces
- type Room
- type Server
- func (s *Server) Ask(ctx context.Context, msg Message) (Message, error)
- func (s *Server) Broadcast(exceptSender fmt.Stringer, msgs ...Message)
- func (s *Server) Close()
- func (s *Server) Do(fn func(*Conn), async bool)
- func (s *Server) GetConnections() map[string]*Conn
- func (s *Server) GetConnectionsByNamespace(namespace string) map[string]*NSConn
- func (s *Server) GetTotalConnections() uint64
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) Upgrade(w http.ResponseWriter, r *http.Request, socketWrapper func(Socket) Socket, ...) (*Conn, error)
- func (s *Server) UseStackExchange(exc StackExchange) error
- type Socket
- type StackExchange
- type StackExchangeInitializer
- type Struct
- func (s *Struct) Events() Events
- func (s *Struct) GetNamespaces() Namespaces
- func (s *Struct) SetEventMatcher(matcher EventMatcherFunc) *Struct
- func (s *Struct) SetInjector(fn StructInjector) *Struct
- func (s *Struct) SetNamespace(namespace string) *Struct
- func (s *Struct) SetTimeouts(read, write time.Duration) *Struct
- type StructInjector
- type Upgrader
- type WithTimeout
Constants ¶
const ( TextMessage = iota + 1 BinaryMessage )
See `MessageType` definition for details.
const URLParamAsHeaderPrefix = "X-Websocket-Header-"
URLParamAsHeaderPrefix is the prefix that server parses the url parameters as request headers. The client's `URLParamAsHeaderPrefix` must match. Note that this is mostly useful for javascript browser-side clients, nodejs and go client support custom headers by default. No action required from end-developer, exported only for chance to a custom parsing.
Variables ¶
var ( // EventPrefixMatcher matches methods to events based on the "prefix". EventPrefixMatcher = func(prefix string) EventMatcherFunc { return func(methodName string) (string, bool) { if strings.HasPrefix(methodName, prefix) { return methodName, true } return "", false } } // EventTrimPrefixMatcher matches methods based on the "prefixToTrim" // and events are registered without this prefix. EventTrimPrefixMatcher = func(prefixToTrim string) EventMatcherFunc { return func(methodName string) (string, bool) { if strings.HasPrefix(methodName, prefixToTrim) { return methodName[len(prefixToTrim):], true } return "", false } } )
var ( // OnNamespaceConnect is the event name which its callback is fired right before namespace connect, // if non-nil error then the remote connection's `Conn.Connect` will fail and send that error text. // Connection is not ready to emit data to the namespace. OnNamespaceConnect = "_OnNamespaceConnect" // OnNamespaceConnected is the event name which its callback is fired after namespace successfully connected. // Connection is ready to emit data back to the namespace. OnNamespaceConnected = "_OnNamespaceConnected" // OnNamespaceDisconnect is the event name which its callback is fired when // remote namespace disconnection or local namespace disconnection is happening. // For server-side connections the reply matters, so if error returned then the client-side cannot disconnect yet, // for client-side the return value does not matter. OnNamespaceDisconnect = "_OnNamespaceDisconnect" // if allowed to connect then it's allowed to disconnect as well. // OnRoomJoin is the event name which its callback is fired right before room join. OnRoomJoin = "_OnRoomJoin" // able to check if allowed to join. // OnRoomJoined is the event name which its callback is fired after the connection has successfully joined to a room. OnRoomJoined = "_OnRoomJoined" // able to broadcast messages to room. // OnRoomLeave is the event name which its callback is fired right before room leave. OnRoomLeave = "_OnRoomLeave" // able to broadcast bye-bye messages to room. // OnRoomLeft is the event name which its callback is fired after the connection has successfully left from a room. OnRoomLeft = "_OnRoomLeft" // if allowed to join to a room, then its allowed to leave from it. // OnAnyEvent is the event name which its callback is fired when incoming message's event is not declared to the ConnHandler(`Events` or `Namespaces`). OnAnyEvent = "_OnAnyEvent" // when event no match. // OnNativeMessage is fired on incoming native/raw websocket messages. // If this event defined then an incoming message can pass the check (it's an invalid message format) // with just the Message's Body filled, the Event is "OnNativeMessage" and IsNative always true. // This event should be defined under an empty namespace in order this to work. OnNativeMessage = "_OnNativeMessage" )
var ( // DefaultMarshaler is a global, package-level alternative for `MessageObjectMarshaler`. // It's used when the `Marshal.v` parameter is not a `MessageObjectMarshaler`. DefaultMarshaler = json.Marshal // DefaultUnmarshaler is a global, package-level alternative for `MessageObjectMarshaler`. // It's used when the `Message.Unmarshal.outPtr` parameter is not a `MessageObjectUnmarshaler`. DefaultUnmarshaler = json.Unmarshal )
var ( // ErrBadNamespace may return from a `Conn#Connect` method when the remote side does not declare the given namespace. ErrBadNamespace = errors.New("bad namespace") // ErrBadRoom may return from a `Room#Leave` method when trying to leave from a not joined room. ErrBadRoom = errors.New("bad room") // ErrWrite may return from any connection's method when the underline connection is closed (unexpectedly). ErrWrite = errors.New("write closed") )
var ErrInvalidPayload = errors.New("invalid payload")
ErrInvalidPayload can be returned by the internal `handleMessage`. In the future it may be exposed by an error listener.
Functions ¶
func DebugEach ¶
func DebugEach(mapOrSlice interface{}, onDebugVisitor interface{})
DebugEach prints debug messages for each of "mapOrSlice" elements to the printer defined on `EnableDebug`. Runs only on debug mode. Usage:
DebugEach(staticFields, func(idx int, f reflect.Value) { fval := f.Interface() Debugf("field [%s.%s] will be automatically re-filled with [%T(%s)]", typ.Name(), typ.Field(idx).Name, fval, fval) })
func Debugf ¶
func Debugf(format string, args ...interface{})
Debugf prints debug messages to the printer defined on `EnableDebug`. Runs only on debug mode.
func EnableDebug ¶
func EnableDebug(printer interface{})
EnableDebug enables debug and optionally sets a custom printer to print out debug messages. The "printer" can be any compatible printer such as the standard `log.Logger` or a custom one like the `kataras/golog`.
A "printer" is compatible when it contains AT LEAST ONE of the following methods: Debugf(string, ...interface{}) or Logf(string, ...interface{}) or Printf(string, ...interface{})
If EnableDebug is called but the "printer" value is nil then neffos will print debug messages through a new log.Logger prefixed with "| neffos |".
Note that neffos, currently, uses debug mode only on the build state of the events. Therefore enabling the debugger has zero performance cost on up-and-running servers and clients.
There is no way to disable the debug mode on serve-time.
func Exclude ¶
Exclude can be passed on `Server#Broadcast` when caller does not have access to the `Conn`, `NSConn` or a `Room` value but has access to a string variable which is a connection's ID instead.
Example Code: nsConn.Conn.Server().Broadcast(
neffos.Exclude("connection_id_here"), neffos.Message{Namespace: "default", Room: "roomName or empty", Event: "chat", Body: [...]})
func IsCloseError ¶
IsCloseError reports whether the "err" is a "closed by the remote host" network connection error.
func IsDisconnectError ¶
IsDisconnectError reports whether the "err" is a timeout or a closed connection error.
func IsSystemEvent ¶
IsSystemEvent reports whether the "event" is a system event, OnNamespaceConnect, OnNamespaceConnected, OnNamespaceDisconnect, OnRoomJoin, OnRoomJoined, OnRoomLeave and OnRoomLeft.
func IsTimeoutError ¶
IsTimeoutError reports whether the "err" is caused by a defined timeout.
func IsTryingToReconnect ¶
IsTryingToReconnect reports whether the returning "err" from the `Server#Upgrade` is from a client that was trying to reconnect to the websocket server.
Look the `Conn#WasReconnected` and `Conn#ReconnectTries` too.
func Marshal ¶
func Marshal(v interface{}) []byte
Marshal marshals the "v" value and returns a Message's Body. If the "v" value is `MessageObjectMarshaler` then it returns the result of its `Marshal` method, otherwise the DefaultMarshaler will be used instead. Errors are pushed to the result, use the object's Marshal method to catch those when necessary.
func RegisterKnownError ¶
func RegisterKnownError(err error)
RegisterKnownError registers an error that it's "known" to both server and client sides. This simply adds an error to a list which, if its static text matches an incoming error text then its value is set to the `Message.Error` field on the events callbacks.
For dynamic text error, there is a special case which if the error "err" contains a `ResolveError(errorText string) bool` method then, it is used to report whether this "err" is match to the incoming error text.
Types ¶
type Client ¶
type Client struct { // ID comes from server, local changes are not reflected, // use the `Server#IDGenerator` if you want to set a custom logic for ID set. ID string // NotifyClose can be optionally registered to notify about the client's disconnect. // This callback is for the entire client side connection, // the channel is notified after namespace disconnected and any room left events. // Don't confuse it with the `OnNamespaceDisconnect` event. // Usage: // <- client.NotifyClose // blocks until local `Close` or remote close of connection. NotifyClose <-chan struct{} // contains filtered or unexported fields }
Client is the neffos client. Contains the neffos client-side connection and the ID came from server on acknowledgement process of the `Dial` function. Use its `Connect` to connect to a namespace or `WaitServerConnect` to wait for server to force-connect this client to a namespace.
func Dial ¶
Dial establishes a new neffos client connection. Context "ctx" is used for handshake timeout. Dialer "dial" can be either `gobwas.Dialer/DefaultDialer` or `gorilla.Dialer/DefaultDialer`, custom dialers can be used as well when complete the `Socket` and `Dialer` interfaces for valid client. URL "url" is the endpoint of the neffos server, i.e "ws://localhost:8080/echo". The last parameter, and the most important one is the "connHandler", it can be filled as `Namespaces`, `Events` or `WithTimeout`, same namespaces and events can be used on the server-side as well.
See examples for more.
func (*Client) Close ¶
func (c *Client) Close()
Close method terminates the client-side connection. Forces the client to disconnect from all connected namespaces and leave from all joined rooms, server gets notified.
func (*Client) Connect ¶
Connect method returns a new connected to the specific "namespace" `NSConn` value. The "namespace" should be declared in the `connHandler` of both server and client sides. Returns error if server-side's `OnNamespaceConnect` event callback returns an error.
See `Conn#Connect` for more details.
type CloseError ¶
type CloseError struct { Code int // contains filtered or unexported fields }
CloseError can be used to send and close a remote connection in the event callback's return statement.
func (CloseError) Error ¶
func (err CloseError) Error() string
type Conn ¶
type Conn struct { // ReconnectTries, if > 0 then this connection is a result of a client-side reconnection, // see `WasReconnected() bool`. ReconnectTries int // contains filtered or unexported fields }
Conn contains the websocket connection and the neffos communication functionality. Its `Connection` will return a new `NSConn` instance. Each connection can connect to one or more declared namespaces. Each `NSConn` can join to multiple rooms.
func (*Conn) Ask ¶
Ask method sends a message to the remote side and blocks until a response or an error received from the specific `Message.Event`.
func (*Conn) Close ¶
func (c *Conn) Close()
Close method will force-disconnect from all connected namespaces and force-leave from all joined rooms and finally will terminate the underline websocket connection. After this method call the `Conn` is not usable anymore, a new `Dial` call is required.
func (*Conn) Connect ¶
Connect method returns a new connected to the specific "namespace" `NSConn` value. The "namespace" should be declared in the `connHandler` of both server and client sides. If this is a client-side connection then the server-side namespace's `OnNamespaceConnect` event callback MUST return null in order to allow this client-side connection to connect, otherwise a non-nil error is returned instead.
func (*Conn) Decrement ¶
Decrement works like `Set` method. It's just a helper for decrementing integer values. If value does exist, and it's an integer then it decrements it by 1, otherwise the value is overridden to value -1. If value does not exist, then it assumes the default value is 0 and it decrements it by one, the result will be -1.
Calling it twice for example it will set the value to -2, even if doesn't exist before.
Returns the decremented value.
func (*Conn) DeserializeMessage ¶
func (c *Conn) DeserializeMessage(msgTyp MessageType, payload []byte) Message
DeserializeMessage returns a Message from the "payload".
func (*Conn) DisconnectAll ¶
DisconnectAll method disconnects from all namespaces, `OnNamespaceDisconnect` even will be fired and its `Message.IsLocal` will be true. The remote side gets notified.
func (*Conn) GetConnectedNamespaceNames ¶
GetConnectedNamespaceNames returns the names of all currently connected namespaces.
func (*Conn) GetServerConnID ¶
GetServerConnID method gets connection's serverConnID
func (*Conn) HandlePayload ¶
func (c *Conn) HandlePayload(msgTyp MessageType, payload []byte) error
HandlePayload fires manually a local event based on the "payload".
func (*Conn) ID ¶
ID method returns the unique identifier of the connection. If this is a server-side connection then this value is the generated one by the `Server#IDGenerator`. If this is a client-side connection then this value is filled on the acknowledgment process which is done on the `Client#Dial`.
func (*Conn) Increment ¶
Increment works like `Set` method. It's just a helper for incrementing integer values. If value does exist, and it's an integer then it increments it by 1, otherwise the value is overridden to value 1. If value does not exist, then it assumes the default value is 0 and it increments it by one, the result will be 1.
Returns the incremented value.
func (*Conn) Is ¶
Is reports whether the "connID" is part of this server's connections and their IDs are equal.
func (*Conn) IsClient ¶
IsClient method reports whether this connections is a client-side connetion.
func (*Conn) IsClosed ¶
IsClosed method reports whether this connection is remotely or manually terminated.
func (*Conn) Namespace ¶
Namespace method returns an already-connected `NSConn` value based on the given "namespace".
func (*Conn) Server ¶
Server method returns the backend server, it returns null on client-side connections.
func (*Conn) String ¶
String method simply returns the ID(). Useful for fmt usage and to a connection to be passed on `Server#Broadcast` method to exclude itself from the broadcasted message's receivers.
func (*Conn) WaitConnect ¶
WaitConnect method can be used instead of the `Connect` if the other side force-calls `Connect` to this connection and this side wants to "waits" for that signal.
Nil context means try without timeout, wait until it connects to the specific namespace. Note that, this function will not return an `ErrBadNamespace` if namespace does not exist in the server-side or it's not defined in the client-side, it waits until deadline (if any, or loop forever, so a context with deadline is highly recommended).
func (*Conn) WasReconnected ¶
WasReconnected reports whether the current connection is a result of a client-side reconnection. To get the numbers of total retries see the `ReconnectTries` field.
type ConnHandler ¶
type ConnHandler interface {
GetNamespaces() Namespaces
}
ConnHandler is the interface which namespaces and events can be retrieved through. Built-in ConnHandlers are the`Events`, `Namespaces`, `WithTimeout` and `NewStruct`. Users of this are the `Dial`(client) and `New` (server) functions.
func JoinConnHandlers ¶
func JoinConnHandlers(connHandlers ...ConnHandler) ConnHandler
JoinConnHandlers combines two or more "connHandlers" and returns a result of a single `ConnHandler` that can be passed on the `New` and `Dial` functions.
type Dialer ¶
Dialer is the definition type of a dialer, gorilla or gobwas or custom. It is the second parameter of the `Dial` function.
type EventMatcherFunc ¶
EventMatcherFunc is a type of which a Struct matches the methods with neffos events.
type Events ¶
type Events map[string]MessageHandlerFunc
Events completes the `ConnHandler` interface. It is a map which its key is the event name and its value the event's callback.
Events type completes the `ConnHandler` itself therefore, can be used as standalone value on the `New` and `Dial` functions to register events on empty namespace as well.
See `Namespaces`, `New` and `Dial` too.
func (Events) GetNamespaces ¶
func (e Events) GetNamespaces() Namespaces
GetNamespaces returns an empty namespace with the "e" Events.
func (Events) On ¶
func (e Events) On(eventName string, msgHandler MessageHandlerFunc)
On is a shortcut of Events { eventName: msgHandler }. It registers a callback "msgHandler" for an event "eventName".
type IDGenerator ¶
type IDGenerator func(w http.ResponseWriter, r *http.Request) string
IDGenerator is the type of function that it is used to generate unique identifiers for new connections.
See `Server.IDGenerator`.
var DefaultIDGenerator IDGenerator = func(http.ResponseWriter, *http.Request) string { id, err := uuid.NewV4() if err != nil { return strconv.FormatInt(time.Now().Unix(), 10) } return id.String() }
DefaultIDGenerator returns a universal unique identifier for a new connection. It's the default `IDGenerator` for `Server`.
type Message ¶
type Message struct { // The Namespace that this message sent to/received from. Namespace string // The Room that this message sent to/received from. Room string // The Event that this message sent to/received from. Event string // The actual body of the incoming/outcoming data. Body []byte // The Err contains any message's error, if any. // Note that server-side and client-side connections can return an error instead of a message from each event callbacks, // except the clients's force Disconnect which its local event doesn't matter when disconnected manually. Err error // When sent by the same connection of the current running server instance. // This field is serialized/deserialized but it's clean on sending or receiving from a client // and it's only used on StackExchange feature. // It's serialized as the first parameter, instead of wait signal, if incoming starts with 0x. FromExplicit string // the exact Conn's pointer in this server instance. // Reports whether this message is coming from a stackexchange. // This field is not exposed and it's not serialized at all, ~local-use only~. // // The "wait" field can determinate if this message is coming from a stackexchange using its second char, // This value set based on "wait" on deserialization when coming from remote side. // Only server-side can actually set it. FromStackExchange bool // To is the connection ID of the receiver, used only when `Server#Broadcast` is called, indeed when we only need to send a message to a single connection. // The Namespace, Room are still respected at all. // // However, sending messages to a group of connections is done by the `Room` field for groups inside a namespace or just `Namespace` field as usual. // This field is not filled on sending/receiving. To string // True when event came from local (i.e client if running client) on force disconnection, // i.e OnNamespaceDisconnect and OnRoomLeave when closing a conn. // This field is not filled on sending/receiving. // Err does not matter and never sent to the other side. IsForced bool // True when asking the other side and fire the respond's event (which matches the sent for connect/disconnect/join/leave), // i.e if a client (or server) onnection want to connect // to a namespace or join to a room. // Should be used rarely, state can be checked by `Conn#IsClient() bool`. // This field is not filled on sending/receiving. IsLocal bool // True when user define it for writing, only its body is written as raw native websocket message, namespace, event and all other fields are empty. // The receiver should accept it on the `OnNativeMessage` event. // This field is not filled on sending/receiving. IsNative bool // if server or client should write using Binary message or if the incoming message was readen as binary. SetBinary bool // contains filtered or unexported fields }
The Message is the structure which describes the incoming and outcoming data. Emitter's "body" argument is the `Message.Body` field. Emitter's return non-nil error is the `Message.Err` field. If native message sent then the `Message.Body` is filled with the body and when incoming native message then the `Message.Event` is the `OnNativeMessage`, native messages are allowed only when an empty namespace("") and its `OnNativeMessage` callback are present.
The the raw data received/sent structured following this order: <wait()>; <namespace>; <room>; <event>; <isError(0-1)>; <isNoOp(0-1)>; <body||error_message>
Internal `serializeMessage` and exported `DeserializeMessage` functions do the job on `Conn#Write`, `NSConn#Emit` and `Room#Emit` calls.
func DeserializeMessage ¶
func DeserializeMessage(msgTyp MessageType, b []byte, allowNativeMessages, shouldHandleOnlyNativeMessages bool) Message
DeserializeMessage accepts a serialized message []byte and returns a neffos Message. When allowNativeMessages only Body is filled and check about message format is skipped.
type MessageHandlerFunc ¶
MessageHandlerFunc is the definition type of the events' callback. Its error can be written to the other side on specific events, i.e on `OnNamespaceConnect` it will abort a remote namespace connection. See examples for more.
type MessageObjectMarshaler ¶
MessageObjectMarshaler is an optional interface that "objects" can implement to customize their byte representation, see `Object` package-level function.
type MessageObjectUnmarshaler ¶
MessageObjectUnmarshaler is an optional interface that "objects" can implement to customize their structure, see `Message.Object` method.
type MessageType ¶
type MessageType uint8
MessageType is a type for readen and to-send data, helpful to set `msg.SetBinary` to the rest of the clients through a Broadcast, as SetBinary is not part of the deserialization.
type NSConn ¶
type NSConn struct { Conn *Conn // contains filtered or unexported fields }
NSConn describes a connection connected to a specific namespace, it emits with the `Message.Namespace` filled and it can join to multiple rooms. A single `Conn` can be connected to one or more namespaces, each connected namespace is described by this structure.
func (*NSConn) Ask ¶
Ask method writes a message to the remote side and blocks until a response or an error received.
func (*NSConn) Disconnect ¶
Disconnect method sends a disconnect signal to the remote side and fires the local `OnNamespaceDisconnect` event.
func (*NSConn) Emit ¶
Emit method sends a message to the remote side with its `Message.Namespace` filled to this specific namespace.
func (*NSConn) EmitBinary ¶
EmitBinary acts like `Emit` but it sets the `Message.SetBinary` to true and sends the data as binary, the receiver's Message in javascript-side is Uint8Array.
func (*NSConn) JoinRoom ¶
JoinRoom method can be used to join a connection to a specific room, rooms are dynamic. Returns the joined `Room`.
func (*NSConn) LeaveAll ¶
LeaveAll method sends a remote and local leave room signal `OnRoomLeave` to and for all rooms and fires the `OnRoomLeft` event if succeed.
type Namespaces ¶
Namespaces completes the `ConnHandler` interface. Can be used to register one or more namespaces on the `New` and `Dial` functions. The key is the namespace literal and the value is the `Events`, a map with event names and their callbacks.
See `WithTimeout`, `New` and `Dial` too.
func (Namespaces) GetNamespaces ¶
func (nss Namespaces) GetNamespaces() Namespaces
GetNamespaces just returns the "nss" namespaces.
func (Namespaces) On ¶
func (nss Namespaces) On(namespace, eventName string, msgHandler MessageHandlerFunc) Events
On is a shortcut of Namespaces { namespace: Events: { eventName: msgHandler } }. It registers a callback "msgHandler" for an event "eventName" of the particular "namespace".
type Room ¶
Room describes a connected connection to a room, emits messages with the `Message.Room` filled to the specific room and `Message.Namespace` to the underline `NSConn`'s namespace.
func (*Room) Emit ¶
Emit method sends a message to the remote side with its `Message.Room` filled to this specific room and `Message.Namespace` to the underline `NSConn`'s namespace.
type Server ¶
type Server struct { IDGenerator IDGenerator StackExchange StackExchange // If `StackExchange` is set then this field is ignored. // // It overrides the default behavior(when no StackExchange is not used) // which publishes a message independently. // In short the default behavior doesn't wait for a message to be published to all clients // before any next broadcast call. // // Therefore, if set to true, // each broadcast call will publish its own message(s) by order. SyncBroadcaster bool // FireDisconnectAlways will allow firing the `OnDisconnect` server's // event even if the connection wasimmediately closed from the `OnConnect` server's event // through `Close()` or non-nil error. // See https://github.com/kataras/neffos/issues/41 // // Defaults to false. FireDisconnectAlways bool // OnUpgradeError can be optionally registered to catch upgrade errors. OnUpgradeError func(err error) // OnConnect can be optionally registered to be notified for any new neffos client connection, // it can be used to force-connect a client to a specific namespace(s) or to send data immediately or // even to cancel a client connection and dissalow its connection when its return error value is not nil. // Don't confuse it with the `OnNamespaceConnect`, this callback is for the entire client side connection. OnConnect func(c *Conn) error // OnDisconnect can be optionally registered to notify about a connection's disconnect. // Don't confuse it with the `OnNamespaceDisconnect`, this callback is for the entire client side connection. OnDisconnect func(c *Conn) // contains filtered or unexported fields }
Server is the neffos server. Keeps the `IDGenerator` which can be customized, by default it's the `DefaultIDGenerator` which generates connections unique identifiers using the uuid/v4.
Callers can optionally register callbacks for connection, disconnection and errored. Its most important methods are `ServeHTTP` which is used to register the server on a specific endpoint and `Broadcast` and `Close`. Use the `New` function to create a new server, server starts automatically, no further action is required.
func New ¶
func New(upgrader Upgrader, connHandler ConnHandler) *Server
New constructs and returns a new neffos server. Listens to incoming connections automatically, no further action is required from the caller. The second parameter is the "connHandler", it can be filled as `Namespaces`, `Events` or `WithTimeout`, same namespaces and events can be used on the client-side as well, Use the `Conn#IsClient` on any event callback to determinate if it's a client-side connection or a server-side one.
See examples for more.
func (*Server) Ask ¶
Ask is like `Broadcast` but it blocks until a response from a specific connection if "msg.To" is filled otherwise from the first connection which will reply to this "msg".
Accepts a context for deadline as its first input argument. The second argument is the request message which should be sent to a specific namespace:event like the `Conn.Ask`.
func (*Server) Broadcast ¶
Broadcast method is fast and does not block any new incoming connection by-default, it can be used as frequently as needed. Use the "msg"'s Namespace, or/and Event or/and Room to broadcast to a specific type of connection collectives.
If first "exceptSender" parameter is not nil then the message "msg" will be broadcasted to all connected clients except the given connection's ID, any value that completes the `fmt.Stringer` interface is valid. Keep note that `Conn`, `NSConn`, `Room` and `Exclude(connID) global function` are valid values.
Example Code: nsConn.Conn.Server().Broadcast(
nsConn OR nil, neffos.Message{Namespace: "default", Room: "roomName or empty", Event: "chat", Body: [...]})
Note that it if `StackExchange` is nil then its default behavior doesn't wait for a publish to complete to all clients before any next broadcast call. To change that behavior set the `Server.SyncBroadcaster` to true before server start.
func (*Server) Close ¶
func (s *Server) Close()
Close terminates the server and all of its connections, client connections are getting notified.
func (*Server) Do ¶
Do loops through all connected connections and fires the "fn", with this method callers can do whatever they want on a connection outside of a event's callback, but make sure that these operations are not taking long time to complete because it delays the new incoming connections. If "async" is true then this method does not block the flow of the program.
func (*Server) GetConnections ¶
GetConnections can be used as an alternative way to retrieve all connected connections to the server on a specific time point. Do not use this function frequently, it is not designed to be fast or cheap, use it for debugging or logging every 'x' time.
Not thread safe.
func (*Server) GetConnectionsByNamespace ¶
GetConnectionsByNamespace can be used as an alternative way to retrieve all connected connections to a specific "namespace" on a specific time point. Do not use this function frequently, it is not designed to be fast or cheap, use it for debugging or logging every 'x' time. Users should work with the event's callbacks alone, the usability is enough for all type of operations. See `Do` too.
Not thread safe.
func (*Server) GetTotalConnections ¶
GetTotalConnections returns the total amount of the connected connections to the server, it's fast and can be used as frequently as needed.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP completes the `http.Handler` interface, it should be passed on a http server's router to serve this neffos server on a specific endpoint.
func (*Server) Upgrade ¶
func (s *Server) Upgrade( w http.ResponseWriter, r *http.Request, socketWrapper func(Socket) Socket, customIDGen IDGenerator, ) (*Conn, error)
Upgrade handles the connection, same as `ServeHTTP` but it can accept a socket wrapper and a "customIDGen" that overrides the server's IDGenerator and it does return the connection or any errors.
func (*Server) UseStackExchange ¶
func (s *Server) UseStackExchange(exc StackExchange) error
UseStackExchange can be used to add one or more StackExchange to the server. Returns a non-nil error when "exc" completes the `StackExchangeInitializer` interface and its `Init` failed.
Read more at the `StackExchange` type's docs.
type Socket ¶
type Socket interface { // NetConn returns the underline net connection. NetConn() net.Conn // Request returns the http request value. Request() *http.Request // ReadData reads binary or text messages from the remote connection. ReadData(timeout time.Duration) (body []byte, typ MessageType, err error) // WriteBinary sends a binary message to the remote connection. WriteBinary(body []byte, timeout time.Duration) error // WriteText sends a text message to the remote connection. WriteText(body []byte, timeout time.Duration) error }
Socket is the interface that an underline protocol implementation should implement.
type StackExchange ¶
type StackExchange interface { // OnConnect should prepare the connection's subscriber. // It's called automatically after the neffos server's OnConnect (if any) // on incoming client connections. OnConnect(c *Conn) error // OnDisconnect should close the connection's subscriber that // created on the `OnConnect` method. // It's called automatically when a connection goes offline, // manually by server or client or by network failure. OnDisconnect(c *Conn) // Publish should publish messages through a stackexchange. // It's called automatically on neffos broadcasting. Publish(msgs []Message) bool // Subscribe should subscribe to a specific namespace, // it's called automatically on neffos namespace connected. Subscribe(c *Conn, namespace string) // Unsubscribe should unsubscribe from a specific namespace, // it's called automatically on neffos namespace disconnect. Unsubscribe(c *Conn, namespace string) // should close the subscriber. // Ask should be able to perform a server Ask to a specific client or to all clients // It blocks until response from a specific client if msg.To is filled, // otherwise will return on the first responder's reply. Ask(ctx context.Context, msg Message, token string) (Message, error) // NotifyAsk should notify and unblock a subscribed connection for this // specific message, "token" is the neffos wait signal for this message. NotifyAsk(msg Message, token string) error }
StackExchange is an optional interface that can be used to change the way neffos sends messages to its clients, i.e communication between multiple neffos servers.
See the "kataras/neffos/stackexchange" subpackage for more details. Real-World example and usage documentation can be found at: "kataras/neffos/_examples/redis".
type StackExchangeInitializer ¶
type StackExchangeInitializer interface { // Init should initialize a stackexchange, it's optional. Init(Namespaces) error }
StackExchangeInitializer is an optional interface for a `StackExchange`. It contains a single `Init` method which accepts the registered server namespaces and returns error. It does not called on manual `Server.StackExchange` field set, use the `Server.UseStackExchange` to make sure that this implementation is respected.
type Struct ¶
type Struct struct {
// contains filtered or unexported fields
}
Struct is a ConnHandler. All fields are unexported, use `NewStruct` instead. It converts any pointer to a struct value to `neffos.Namespaces` using reflection.
func NewStruct ¶
func NewStruct(ptr interface{}) *Struct
NewStruct returns a new Struct value instance type of ConnHandler. The "ptr" should be a pointer to a struct. This function is used when you want to convert a structure to neffos.ConnHandler based on the struct's methods. The methods if "ptr" structure value can be func(msg neffos.Message) error if the structure contains a *neffos.NSConn field, otherwise they should be like any event callback: func(nsConn *neffos.NSConn, msg neffos.Message) error. If contains a field of type *neffos.NSConn then on each new connection to the namespace a new controller is created and static fields(if any) are set on runtime with the NSConn itself. If it's a static controller (does not contain a NSConn field) then it just registers its functions as regular events without performance cost.
Users of this method is `New` and `Dial`.
Note that this method has a tiny performance cost when an event's callback's logic has small footprint.
func (*Struct) Events ¶
Events builds and returns the Events. Callers of this method is users that want to add Structs to different namespaces in the same application. When a single namespace is used then this call is unnecessary, the `Struct` is already a fully featured `ConnHandler` by itself.
func (*Struct) GetNamespaces ¶
func (s *Struct) GetNamespaces() Namespaces
GetNamespaces creates and returns Namespaces based on the pointer to struct value provided by the "s".
func (*Struct) SetEventMatcher ¶
func (s *Struct) SetEventMatcher(matcher EventMatcherFunc) *Struct
SetEventMatcher sets an event method matcher which applies to every event except the system events (OnNamespaceConnected, and so on).
func (*Struct) SetInjector ¶
func (s *Struct) SetInjector(fn StructInjector) *Struct
SetInjector sets a custom injector and overrides the neffos default behavior on dynamic structs. The "fn" should handle to fill static fields and the NSConn. This "fn" will only be called when dynamic struct "ptr" is passed on the `NewStruct`. The caller should return a valid type of "ptr" reflect.Value.
func (*Struct) SetNamespace ¶
SetNamespace sets a namespace that this Struct is responsible for, Alterinatively create a method on the controller named `Namespace() string` to retrieve this namespace at build time.
func (*Struct) SetTimeouts ¶
SetTimeouts sets read and write deadlines on the underlying network connection. After a read or write have timed out, the websocket connection is closed.
Defaults to 0, no timeout except an `Upgrader` or `Dialer` specifies its own values.
type StructInjector ¶
StructInjector is a type which injects a dynamic struct value. See `Struct.SetInjector` for more.
type Upgrader ¶
Upgrader is the definition type of a protocol upgrader, gorilla or gobwas or custom. It is the first parameter of the `New` function which constructs a neffos server.
type WithTimeout ¶
type WithTimeout struct { ReadTimeout time.Duration WriteTimeout time.Duration Namespaces Namespaces Events Events }
WithTimeout completes the `ConnHandler` interface. Can be used to register namespaces and events or just events on an empty namespace with Read and Write timeouts.
See `New` and `Dial`.
func (WithTimeout) GetNamespaces ¶
func (t WithTimeout) GetNamespaces() Namespaces
GetNamespaces returns combined namespaces from "Namespaces" and "Events" fields with read and write timeouts from "ReadTimeout" and "WriteTimeout" fields of "t".