socket

package
v2.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 19, 2023 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	SOCKET_RESERVED_EVENTS         = types.NewSet("connect", "connect_error", "disconnect", "disconnecting", "newListener", "removeListener")
	RECOVERABLE_DISCONNECT_REASONS = types.NewSet("transport error", "transport close", "forced close", "ping timeout", "server shutting down", "forced server close")
)
View Source
var (
	NAMESPACE_RESERVED_EVENTS = types.NewSet("connect", "connection", "new_namespace")
)

Functions

This section is empty.

Types

type Adapter

type Adapter interface {
	events.EventEmitter

	Prototype(Adapter)
	Proto() Adapter

	Rooms() *types.Map[Room, *types.Set[SocketId]]
	Sids() *types.Map[SocketId, *types.Set[Room]]
	Nsp() NamespaceInterface

	// Construct() should be called after calling Prototype()
	Construct(NamespaceInterface)

	// To be overridden
	Init()

	// To be overridden
	Close()

	// Returns the number of Socket.IO servers in the cluster
	ServerCount() int64

	// Adds a socket to a list of room.
	AddAll(SocketId, *types.Set[Room])

	// Removes a socket from a room.
	Del(SocketId, Room)

	// Removes a socket from all rooms it's joined.
	DelAll(SocketId)

	// Broadcasts a packet.
	//
	// Options:
	//  - `Flags` {*BroadcastFlags} flags for this packet
	//  - `Except` {*types.Set[Room]} sids that should be excluded
	//  - `Rooms` {*types.Set[Room]} list of rooms to broadcast to
	Broadcast(*parser.Packet, *BroadcastOptions)

	// Broadcasts a packet and expects multiple acknowledgements.
	//
	// Options:
	//  - `Flags` {*BroadcastFlags} flags for this packet
	//  - `Except` {*types.Set[Room]} sids that should be excluded
	//  - `Rooms` {*types.Set[Room]} list of rooms to broadcast to
	BroadcastWithAck(*parser.Packet, *BroadcastOptions, func(uint64), func([]any, error))

	// Gets a list of sockets by sid.
	Sockets(*types.Set[Room]) *types.Set[SocketId]

	// Gets the list of rooms a given socket has joined.
	SocketRooms(SocketId) *types.Set[Room]

	// Returns the matching socket instances
	FetchSockets(*BroadcastOptions) func(func([]SocketDetails, error))

	// Makes the matching socket instances join the specified rooms
	AddSockets(*BroadcastOptions, []Room)

	// Makes the matching socket instances leave the specified rooms
	DelSockets(*BroadcastOptions, []Room)

	// Makes the matching socket instances disconnect
	DisconnectSockets(*BroadcastOptions, bool)

	// Send a packet to the other Socket.IO servers in the cluster
	ServerSideEmit([]any) error

	// Save the client session in order to restore it upon reconnection.
	PersistSession(*SessionToPersist)

	// Restore the session and find the packets that were missed by the client.
	RestoreSession(PrivateSessionId, string) (*Session, error)
}

func MakeAdapter

func MakeAdapter() Adapter

func MakeSessionAwareAdapter

func MakeSessionAwareAdapter() Adapter

func NewAdapterNew

func NewAdapterNew(nsp NamespaceInterface) Adapter

func NewSessionAwareAdapter

func NewSessionAwareAdapter(nsp NamespaceInterface) Adapter

type AdapterBuilder

type AdapterBuilder struct {
}

func (*AdapterBuilder) New

type AdapterConstructor

type AdapterConstructor interface {
	New(NamespaceInterface) Adapter
}

type BroadcastAdapter

type BroadcastAdapter func(*parser.Packet, *BroadcastOptions)

func (BroadcastAdapter) AddAll

func (BroadcastAdapter) AddAll(SocketId, *types.Set[Room])

func (BroadcastAdapter) AddListener

func (BroadcastAdapter) AddSockets

func (BroadcastAdapter) AddSockets(*BroadcastOptions, []Room)

func (BroadcastAdapter) Broadcast

func (ba BroadcastAdapter) Broadcast(packet *parser.Packet, opts *BroadcastOptions)

func (BroadcastAdapter) BroadcastWithAck

func (BroadcastAdapter) BroadcastWithAck(*parser.Packet, *BroadcastOptions, func(uint64), func([]any, error))

func (BroadcastAdapter) Clear

func (BroadcastAdapter) Clear()

func (BroadcastAdapter) Close

func (BroadcastAdapter) Close()

func (BroadcastAdapter) Construct

Construct() should be called after calling Prototype()

func (BroadcastAdapter) Del

func (BroadcastAdapter) DelAll

func (BroadcastAdapter) DelAll(SocketId)

func (BroadcastAdapter) DelSockets

func (BroadcastAdapter) DelSockets(*BroadcastOptions, []Room)

func (BroadcastAdapter) DisconnectSockets

func (BroadcastAdapter) DisconnectSockets(*BroadcastOptions, bool)

func (BroadcastAdapter) Emit

func (BroadcastAdapter) EventNames

func (BroadcastAdapter) EventNames() []events.EventName

func (BroadcastAdapter) FetchSockets

func (BroadcastAdapter) FetchSockets(*BroadcastOptions) func(func([]SocketDetails, error))

func (BroadcastAdapter) GetMaxListeners

func (BroadcastAdapter) GetMaxListeners() uint

func (BroadcastAdapter) Init

func (BroadcastAdapter) Init()

func (BroadcastAdapter) Len

func (BroadcastAdapter) Len() int

func (BroadcastAdapter) ListenerCount

func (BroadcastAdapter) ListenerCount(events.EventName) int

func (BroadcastAdapter) Listeners

func (BroadcastAdapter) Nsp

func (BroadcastAdapter) On

func (BroadcastAdapter) Once

func (BroadcastAdapter) PersistSession

func (BroadcastAdapter) PersistSession(*SessionToPersist)

func (BroadcastAdapter) Proto

func (ba BroadcastAdapter) Proto() Adapter

func (BroadcastAdapter) Prototype

func (BroadcastAdapter) Prototype(Adapter)

func (BroadcastAdapter) RemoveAllListeners

func (BroadcastAdapter) RemoveAllListeners(events.EventName) bool

func (BroadcastAdapter) RemoveListener

func (BroadcastAdapter) RestoreSession

func (BroadcastAdapter) RestoreSession(PrivateSessionId, string) (*Session, error)

func (BroadcastAdapter) Rooms

func (BroadcastAdapter) ServerCount

func (BroadcastAdapter) ServerCount() int64

func (BroadcastAdapter) ServerSideEmit

func (BroadcastAdapter) ServerSideEmit([]any) error

func (BroadcastAdapter) SetMaxListeners

func (BroadcastAdapter) SetMaxListeners(uint)

func (BroadcastAdapter) Sids

func (BroadcastAdapter) SocketRooms

func (BroadcastAdapter) SocketRooms(SocketId) *types.Set[Room]

func (BroadcastAdapter) Sockets

type BroadcastFlags

type BroadcastFlags struct {
	WriteOptions

	Local     bool           `json:"local" mapstructure:"local" msgpack:"local"`
	Broadcast bool           `json:"broadcast" mapstructure:"broadcast" msgpack:"broadcast"`
	Binary    bool           `json:"binary" mapstructure:"binary" msgpack:"binary"`
	Timeout   *time.Duration `json:"timeout,omitempty" mapstructure:"timeout,omitempty" msgpack:"timeout,omitempty"`

	ExpectSingleResponse bool `json:"expectSingleResponse" mapstructure:"expectSingleResponse" msgpack:"expectSingleResponse"`
}

type BroadcastOperator

type BroadcastOperator struct {
	// contains filtered or unexported fields
}

func MakeBroadcastOperator

func MakeBroadcastOperator() *BroadcastOperator

func NewBroadcastOperator

func NewBroadcastOperator(adapter Adapter, rooms *types.Set[Room], exceptRooms *types.Set[Room], flags *BroadcastFlags) *BroadcastOperator

func (*BroadcastOperator) AllSockets deprecated

func (b *BroadcastOperator) AllSockets() (*types.Set[SocketId], error)

Gets a list of clients.

Deprecated: this method will be removed in the next major release, please use [Server#ServerSideEmit] or [FetchSockets] instead.

func (*BroadcastOperator) Compress

func (b *BroadcastOperator) Compress(compress bool) *BroadcastOperator

Sets the compress flag.

io.Compress(false).Emit("hello")

Param: compress - if `true`, compresses the sending data

Return: a new BroadcastOperator instance

func (*BroadcastOperator) Construct

func (b *BroadcastOperator) Construct(adapter Adapter, rooms *types.Set[Room], exceptRooms *types.Set[Room], flags *BroadcastFlags)

func (*BroadcastOperator) DisconnectSockets

func (b *BroadcastOperator) DisconnectSockets(status bool)

Makes the matching socket instances disconnect.

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances disconnect (the connections might be kept alive for other namespaces)
io.DisconnectSockets(false)

// make all socket instances in the "room1" room disconnect and close the underlying connections
io.In("room1").DisconnectSockets(true)

Param: close - whether to close the underlying connection

func (*BroadcastOperator) Emit

func (b *BroadcastOperator) Emit(ev string, args ...any) error

Emits to all clients.

// the “foo” event will be broadcast to all connected clients
io.Emit("foo", "bar")

// the “foo” event will be broadcast to all connected clients in the “room-101” room
io.To("room-101").Emit("foo", "bar")

// with an acknowledgement expected from all connected clients
io.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
	if err != nil {
		// some clients did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per client
	}
})

func (*BroadcastOperator) EmitWithAck

func (b *BroadcastOperator) EmitWithAck(ev string, args ...any) func(func([]any, error))

Emits an event and waits for an acknowledgement from all clients.

io.Timeout(1000 * time.Millisecond).EmitWithAck("some-event")(func(args []any, err error) {
	if err == nil {
		fmt.Println(args) // one response per client
	} else {
		// some clients did not acknowledge the event in the given delay
	}
})

Return: a `func(func([]any, error))` that will be fulfilled when all clients have acknowledged the event

func (*BroadcastOperator) Except

func (b *BroadcastOperator) Except(room ...Room) *BroadcastOperator

Excludes a room when emitting.

// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
io.Except("room-101").Emit("foo", "bar")

// with an array of rooms
io.Except(["room-101", "room-102"]).Emit("foo", "bar")
io.Except([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
io.Except("room-101").Except("room-102").Emit("foo", "bar")

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*BroadcastOperator) FetchSockets

func (b *BroadcastOperator) FetchSockets() func(func([]*RemoteSocket, error))

Returns the matching socket instances. This method works across a cluster of several Socket.IO servers.

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

io.FetchSockets()(func(sockets []*RemoteSocket, _ error){
	// return all Socket instances
})

// return all Socket instances in the "room1" room
io.In("room1").FetchSockets()(func(sockets []*RemoteSocket, _ error){

	for _, socket := range sockets {
		fmt.Println(socket.Id())
		fmt.Println(socket.Handshake())
		fmt.Println(socket.Rooms())
		fmt.Println(socket.Data())

		socket.Emit("hello")
		socket.Join("room1")
		socket.Leave("room2")
		socket.Disconnect()
	}

})

func (*BroadcastOperator) In

func (b *BroadcastOperator) In(room ...Room) *BroadcastOperator

Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:

// disconnect all clients in the "room-101" room
io.In("room-101").DisconnectSockets(false)

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*BroadcastOperator) Local

Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.

// the “foo” event will be broadcast to all connected clients on this node
io.Local().Emit("foo", "bar")

Return: a new BroadcastOperator instance for chaining

func (*BroadcastOperator) SocketsJoin

func (b *BroadcastOperator) SocketsJoin(room ...Room)

Makes the matching socket instances join the specified rooms.

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances join the "room1" room
io.SocketsJoin("room1")

// make all socket instances in the "room1" room join the "room2" and "room3" rooms
io.In("room1").SocketsJoin([]Room{"room2", "room3"}...)

Param: Room - a `Room`, or a `Room` slice to expand

func (*BroadcastOperator) SocketsLeave

func (b *BroadcastOperator) SocketsLeave(room ...Room)

Makes the matching socket instances leave the specified rooms.

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances leave the "room1" room
io.SocketsLeave("room1")

// make all socket instances in the "room1" room leave the "room2" and "room3" rooms
io.In("room1").SocketsLeave([]Room{"room2", "room3"}...)

Param: Room - a `Room`, or a `Room` slice to expand

func (*BroadcastOperator) Timeout

func (b *BroadcastOperator) Timeout(timeout time.Duration) *BroadcastOperator

Adds a timeout in milliseconds for the next operation

io.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
	if err != nil {
		// some clients did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per client
	}
})

Param: timeout

func (*BroadcastOperator) To

func (b *BroadcastOperator) To(room ...Room) *BroadcastOperator

Targets a room when emitting.

// the “foo” event will be broadcast to all connected clients in the “room-101” room
io.To("room-101").Emit("foo", "bar")

// with an array of rooms (a client will be notified at most once)
io.To("room-101", "room-102").Emit("foo", "bar")
io.To([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
io.To("room-101").To("room-102").Emit("foo", "bar")

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*BroadcastOperator) Volatile

func (b *BroadcastOperator) Volatile() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to receive messages (because of network slowness or other issues, or because they’re connected through long polling and is in the middle of a request-response cycle).

io.Volatile().Emit("hello") // the clients may or may not receive it

type BroadcastOptions

type BroadcastOptions struct {
	Rooms  *types.Set[Room]
	Except *types.Set[Room]
	Flags  *BroadcastFlags `json:"flags,omitempty" mapstructure:"flags,omitempty" msgpack:"flags,omitempty"`
}

type Client

type Client struct {
	// contains filtered or unexported fields
}

func MakeClient

func MakeClient() *Client

func NewClient

func NewClient(server *Server, conn engine.Socket) *Client

func (*Client) Conn

func (c *Client) Conn() engine.Socket

func (*Client) Construct

func (c *Client) Construct(server *Server, conn engine.Socket)

Client constructor.

Param: server instance

Param: conn

func (*Client) Request

func (c *Client) Request() *types.HttpContext

Return: the reference to the request that originated the Engine.IO connection

func (*Client) WriteToEngine

func (c *Client) WriteToEngine(encodedPackets []_types.BufferInterface, opts *WriteOptions)

type ConnectionStateRecovery

type ConnectionStateRecovery struct {
	// contains filtered or unexported fields
}

func (*ConnectionStateRecovery) GetRawMaxDisconnectionDuration

func (c *ConnectionStateRecovery) GetRawMaxDisconnectionDuration() *int64

func (*ConnectionStateRecovery) GetRawSkipMiddlewares

func (c *ConnectionStateRecovery) GetRawSkipMiddlewares() *bool

func (*ConnectionStateRecovery) MaxDisconnectionDuration

func (c *ConnectionStateRecovery) MaxDisconnectionDuration() int64

func (*ConnectionStateRecovery) SetMaxDisconnectionDuration

func (c *ConnectionStateRecovery) SetMaxDisconnectionDuration(maxDisconnectionDuration int64)

func (*ConnectionStateRecovery) SetSkipMiddlewares

func (c *ConnectionStateRecovery) SetSkipMiddlewares(skipMiddlewares bool)

func (*ConnectionStateRecovery) SkipMiddlewares

func (c *ConnectionStateRecovery) SkipMiddlewares() bool

type ExtendedError

type ExtendedError struct {
	// contains filtered or unexported fields
}

func NewExtendedError

func NewExtendedError(message string, data any) *ExtendedError

func (*ExtendedError) Data

func (e *ExtendedError) Data() any

func (*ExtendedError) Err

func (e *ExtendedError) Err() error

func (*ExtendedError) Error

func (e *ExtendedError) Error() string

type Handshake

type Handshake struct {
	// The headers sent as part of the handshake
	Headers map[string][]string `json:"headers" mapstructure:"headers" msgpack:"headers"`
	// The date of creation (as string)
	Time string `json:"time" mapstructure:"time" msgpack:"time"`
	// The ip of the client
	Address string `json:"address" mapstructure:"address" msgpack:"address"`
	// Whether the connection is cross-domain
	Xdomain bool `json:"xdomain" mapstructure:"xdomain" msgpack:"xdomain"`
	// Whether the connection is secure
	Secure bool `json:"secure" mapstructure:"secure" msgpack:"secure"`
	// The date of creation (as unix timestamp)
	Issued int64 `json:"issued" mapstructure:"issued" msgpack:"issued"`
	// The request URL string
	Url string `json:"url" mapstructure:"url" msgpack:"url"`
	// The query object
	Query map[string][]string `json:"query" mapstructure:"query" msgpack:"query"`
	// The auth object
	Auth any `json:"auth" mapstructure:"auth" msgpack:"auth"`
}

type Namespace

type Namespace struct {
	*StrictEventEmitter
	// contains filtered or unexported fields
}

A namespace is a communication channel that allows you to split the logic of your application over a single shared connection.

Each namespace has its own:

- event handlers

io.Of("/orders").On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.On("order:list", func(...any){})
	socket.On("order:create", func(...any){})
})

io.Of("/users").On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.On("user:list", func(...any){})
})

- rooms

orderNamespace := io.Of("/orders")

orderNamespace.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.Join("room1")
	orderNamespace.To("room1").Emit("hello")
})

userNamespace := io.Of("/users")

userNamespace.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.Join("room1") // distinct from the room in the "orders" namespace
	userNamespace.To("room1").Emit("holà")
})

- middlewares

orderNamespace := io.Of("/orders")

orderNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ensure the socket has access to the "orders" namespace
})

userNamespace := io.Of("/users")

userNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ensure the socket has access to the "users" namespace
})

func MakeNamespace

func MakeNamespace() *Namespace

func NewNamespace

func NewNamespace(server *Server, name string) *Namespace

func (*Namespace) Adapter

func (n *Namespace) Adapter() Adapter

func (*Namespace) Add

func (n *Namespace) Add(client *Client, auth any, fn func(*Socket))

Adds a new client.

func (*Namespace) AllSockets deprecated

func (n *Namespace) AllSockets() (*types.Set[SocketId], error)

Gets a list of socket ids.

Deprecated: this method will be removed in the next major release, please use [Namespace#ServerSideEmit] or [Namespace#FetchSockets] instead.

func (*Namespace) Compress

func (n *Namespace) Compress(compress bool) *BroadcastOperator

Sets the compress flag.

io.Compress(false).Emit("hello")

Param: bool - if `true`, compresses the sending data

Return: a new BroadcastOperator instance for chaining

func (*Namespace) Construct

func (n *Namespace) Construct(server *Server, name string)

func (*Namespace) DisconnectSockets

func (n *Namespace) DisconnectSockets(status bool)

Makes the matching socket instances disconnect

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances disconnect (the connections might be kept alive for other namespaces)
io.DisconnectSockets(false)

// make all socket instances in the "room1" room disconnect and close the underlying connections
io.In("room1").DisconnectSockets(true)

Param: close - whether to close the underlying connection

func (*Namespace) Emit

func (n *Namespace) Emit(ev string, args ...any) error

Emits to all clients.

myNamespace := io.Of("/my-namespace")

// the “foo” event will be broadcast to all connected clients
myNamespace.Emit("foo", "bar")

// the “foo” event will be broadcast to all connected clients in the “room-101” room
myNamespace.To("room-101").Emit("foo", "bar")

// with an acknowledgement expected from all connected clients
myNamespace.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
	if err != nil {
		// some clients did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per client
	}
})

Return: Always nil

func (*Namespace) EmitWithAck

func (n *Namespace) EmitWithAck(ev string, args ...any) func(func([]any, error))

Emits an event and waits for an acknowledgement from all clients.

myNamespace := io.Of("/my-namespace")

myNamespace.Timeout(1000 * time.Millisecond).EmitWithAck("some-event")(func(args []any, err error) {
	if err == nil {
		fmt.Println(args) // one response per client
	} else {
		// some servers did not acknowledge the event in the given delay
	}
})

Return: a `func(func([]any, error))` that will be fulfilled when all clients have acknowledged the event

func (*Namespace) EventEmitter

func (n *Namespace) EventEmitter() *StrictEventEmitter

func (*Namespace) Except

func (n *Namespace) Except(room ...Room) *BroadcastOperator

Excludes a room when emitting.

myNamespace := io.Of("/my-namespace")

// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
myNamespace.Except("room-101").Emit("foo", "bar")

// with an array of rooms
myNamespace.Except(["room-101", "room-102"]).Emit("foo", "bar")
myNamespace.Except([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
myNamespace.Except("room-101").Except("room-102").Emit("foo", "bar")

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Namespace) FetchSockets

func (n *Namespace) FetchSockets() func(func([]*RemoteSocket, error))

Returns the matching socket instances

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

io.FetchSockets()(func(sockets []*RemoteSocket, _ error){
	// return all Socket instances
})

// return all Socket instances in the "room1" room
io.In("room1").FetchSockets()(func(sockets []*RemoteSocket, _ error){

	for _, socket := range sockets {
		fmt.Println(socket.Id())
		fmt.Println(socket.Handshake())
		fmt.Println(socket.Rooms())
		fmt.Println(socket.Data())

		socket.Emit("hello")
		socket.Join("room1")
		socket.Leave("room2")
		socket.Disconnect()
	}

})

func (*Namespace) Ids

func (n *Namespace) Ids() uint64

func (*Namespace) In

func (n *Namespace) In(room ...Room) *BroadcastOperator

Targets a room when emitting.

myNamespace := io.Of("/my-namespace")

// disconnect all clients in the "room-101" room
myNamespace.In("room-101").DisconnectSockets(false)

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Namespace) InitAdapter

func (n *Namespace) InitAdapter()

@protected

Initializes the `Adapter` for n nsp. Run upon changing adapter by `Server.Adapter` in addition to the constructor.

func (*Namespace) Local

func (n *Namespace) Local() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.

myNamespace := io.Of("/my-namespace")

// the “foo” event will be broadcast to all connected clients on this node
myNamespace.Local().Emit("foo", "bar")

Return: a new BroadcastOperator instance for chaining

func (*Namespace) Name

func (n *Namespace) Name() string

func (*Namespace) OnServerSideEmit

func (n *Namespace) OnServerSideEmit(ev string, args ...any)

Called when a packet is received from another Socket.IO server

func (*Namespace) Proto

func (n *Namespace) Proto() NamespaceInterface

func (*Namespace) Prototype

func (n *Namespace) Prototype(_n NamespaceInterface)

func (*Namespace) Send

func (n *Namespace) Send(args ...any) NamespaceInterface

Sends a `message` event to all clients.

This method mimics the WebSocket.send() method.

See: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send

myNamespace := io.Of("/my-namespace")

myNamespace.Send("hello")

// this is equivalent to
myNamespace.Emit("message", "hello")

func (*Namespace) Server

func (n *Namespace) Server() *Server

func (*Namespace) ServerSideEmit

func (n *Namespace) ServerSideEmit(ev string, args ...any) error

Emit a packet to other Socket.IO servers

myNamespace := io.Of("/my-namespace")

myNamespace.ServerSideEmit("hello", "world")

myNamespace.On("hello", func(args ...any) {
	fmt.Println(args) // prints "world"
})

// acknowledgements (without binary content) are supported too:
myNamespace.ServerSideEmit("ping", func(args []any, err error) {
	if err != nil {
		// some servers did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per server (except the current one)
	}
})

myNamespace.On("ping", func(args ...any) {
	args[0]("pong")
})

Param: ev - the event name

Param: args - an slice of arguments, which may include an acknowledgement callback at the end

func (*Namespace) ServerSideEmitWithAck

func (n *Namespace) ServerSideEmitWithAck(ev string, args ...any) func(func([]any, error))

Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.

myNamespace := io.Of("/my-namespace")

myNamespace.Timeout(1000 * time.Millisecond).ServerSideEmitWithAck("some-event")(func(args []any, err error) {
	if err == nil {
		fmt.Println(args) // one response per client
	} else {
		// some servers did not acknowledge the event in the given delay
	}
})

Return: a `func(func([]any, error))` that will be fulfilled when all servers have acknowledged the event

func (*Namespace) Sockets

func (n *Namespace) Sockets() *types.Map[SocketId, *Socket]

func (*Namespace) SocketsJoin

func (n *Namespace) SocketsJoin(room ...Room)

Makes the matching socket instances join the specified rooms

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances join the "room1" room
io.SocketsJoin("room1")

// make all socket instances in the "room1" room join the "room2" and "room3" rooms
io.In("room1").SocketsJoin([]Room{"room2", "room3"}...)

Param: Room - a `Room`, or a `Room` slice to expand

func (*Namespace) SocketsLeave

func (n *Namespace) SocketsLeave(room ...Room)

Makes the matching socket instances leave the specified rooms

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances leave the "room1" room
io.SocketsLeave("room1")

// make all socket instances in the "room1" room leave the "room2" and "room3" rooms
io.In("room1").SocketsLeave([]Room{"room2", "room3"}...)

Param: Room - a `Room`, or a `Room` slice to expand

func (*Namespace) Timeout

func (n *Namespace) Timeout(timeout time.Duration) *BroadcastOperator

Adds a timeout in milliseconds for the next operation

io.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
	if err != nil {
		// some clients did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per client
	}
})

func (*Namespace) To

func (n *Namespace) To(room ...Room) *BroadcastOperator

Targets a room when emitting.

myNamespace := io.Of("/my-namespace")

// the “foo” event will be broadcast to all connected clients in the “room-101” room
myNamespace.To("room-101").Emit("foo", "bar")

// with an array of rooms (a client will be notified at most once)
myNamespace.To("room-101", "room-102").Emit("foo", "bar")
myNamespace.To([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
myNamespace.To("room-101").To("room-102").Emit("foo", "bar")

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Namespace) Use

func (n *Namespace) Use(fn func(*Socket, func(*ExtendedError))) NamespaceInterface

Registers a middleware, which is a function that gets executed for every incoming Socket.

myNamespace := io.Of("/my-namespace")

myNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ...
	next(nil)
})

Param: func(*ExtendedError) - the middleware function

func (*Namespace) Volatile

func (n *Namespace) Volatile() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to receive messages (because of network slowness or other issues, or because they’re connected through long polling and is in the middle of a request-response cycle).

myNamespace := io.Of("/my-namespace")

myNamespace.Volatile().Emit("hello") // the clients may or may not receive it

func (*Namespace) Write

func (n *Namespace) Write(args ...any) NamespaceInterface

Sends a `message` event to all clients. Sends a `message` event. Alias of [Send].

type NamespaceInterface

type NamespaceInterface interface {
	On(string, ...events.Listener) error
	Once(string, ...events.Listener) error
	EmitReserved(string, ...any)
	EmitUntyped(string, ...any)
	Listeners(string) []events.Listener

	Prototype(NamespaceInterface)
	Proto() NamespaceInterface

	EventEmitter() *StrictEventEmitter
	Sockets() *types.Map[SocketId, *Socket]
	Server() *Server
	Adapter() Adapter
	Name() string
	Ids() uint64

	// Construct() should be called after calling Prototype()
	Construct(*Server, string)

	// @protected
	//
	// Initializes the `Adapter` for n nsp.
	// Run upon changing adapter by `Server.Adapter`
	// in addition to the constructor.
	InitAdapter()

	// Sets up namespace middleware.
	Use(func(*Socket, func(*ExtendedError))) NamespaceInterface

	// Targets a room when emitting.
	To(...Room) *BroadcastOperator

	// Targets a room when emitting.
	In(...Room) *BroadcastOperator

	// Excludes a room when emitting.
	Except(...Room) *BroadcastOperator

	// Adds a new client.
	Add(*Client, any, func(*Socket))

	// Emits to all clients.
	Emit(string, ...any) error

	// Emits an event and waits for an acknowledgement from all clients.
	EmitWithAck(string, ...any) func(func([]any, error))

	// Sends a `message` event to all clients.
	Send(...any) NamespaceInterface

	// Sends a `message` event to all clients.
	Write(...any) NamespaceInterface

	// Emit a packet to other Socket.IO servers
	ServerSideEmit(string, ...any) error

	// Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.
	ServerSideEmitWithAck(string, ...any) func(func([]any, error))

	// @private
	//
	// Called when a packet is received from another Socket.IO server
	OnServerSideEmit(string, ...any)

	// Gets a list of clients.
	AllSockets() (*types.Set[SocketId], error)

	// Sets the compress flag.
	Compress(bool) *BroadcastOperator

	// Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
	// receive messages (because of network slowness or other issues, or because they’re connected through long polling
	// and is in the middle of a request-response cycle).
	Volatile() *BroadcastOperator

	// Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
	Local() *BroadcastOperator

	// Adds a timeout in milliseconds for the next operation
	Timeout(time.Duration) *BroadcastOperator

	// Returns the matching socket instances
	//
	// Deprecated: this method will be removed in the next major release, please use [Server.ServerSideEmit] or [BroadcastOperator.FetchSockets] instead.
	FetchSockets() func(func([]*RemoteSocket, error))

	// Makes the matching socket instances join the specified rooms
	SocketsJoin(...Room)

	// Makes the matching socket instances leave the specified rooms
	SocketsLeave(...Room)

	// Makes the matching socket instances disconnect
	DisconnectSockets(bool)
}

A namespace is a communication channel that allows you to split the logic of your application over a single shared connection.

Each namespace has its own:

- event handlers

io.Of("/orders").On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.On("order:list", func(...any){})
	socket.On("order:create", func(...any){})
})

io.Of("/users").On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.On("user:list", func(...any){})
})

- rooms

orderNamespace := io.Of("/orders")

orderNamespace.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.Join("room1")
	orderNamespace.To("room1").Emit("hello")
})

userNamespace := io.Of("/users")

userNamespace.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.Join("room1") // distinct from the room in the "orders" namespace
	userNamespace.To("room1").Emit("holà")
})

- middlewares

orderNamespace := io.Of("/orders")

orderNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ensure the socket has access to the "orders" namespace
})

userNamespace := io.Of("/users")

userNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ensure the socket has access to the "users" namespace
})

type ParentNamespace

type ParentNamespace struct {
	*Namespace
	// contains filtered or unexported fields
}

A parent namespace is a special Namespace that holds a list of child namespaces which were created either with a regular expression or with a function.

parentNamespace := io.Of(regexp.MustCompile(`/dynamic-\d+`))

parentNamespace.On("connection", func(clients ...any) {
	client := clients[0].(*socket.Socket)
	childNamespace := client.Nsp()
}

// will reach all the clients that are in one of the child namespaces, like "/dynamic-101"

parentNamespace.Emit("hello", "world")

func MakeParentNamespace

func MakeParentNamespace() *ParentNamespace

func NewParentNamespace

func NewParentNamespace(server *Server) *ParentNamespace

func (*ParentNamespace) CreateChild

func (p *ParentNamespace) CreateChild(name string) *Namespace

func (*ParentNamespace) Emit

func (p *ParentNamespace) Emit(ev string, args ...any) error

func (*ParentNamespace) FetchSockets

func (p *ParentNamespace) FetchSockets() func(func([]*RemoteSocket, error))

func (*ParentNamespace) InitAdapter

func (p *ParentNamespace) InitAdapter()

type ParentNspNameMatchFn

type ParentNspNameMatchFn *func(string, any, func(error, bool))

type PersistedPacket

type PersistedPacket struct {
	Id        string            `json:"id" mapstructure:"id" msgpack:"id"`
	EmittedAt int64             `json:"emittedAt" mapstructure:"emittedAt" msgpack:"emittedAt"`
	Data      any               `json:"data" mapstructure:"data" msgpack:"data"`
	Opts      *BroadcastOptions `json:"opts,omitempty" mapstructure:"opts,omitempty" msgpack:"opts,omitempty"`
}

type PrivateSessionId

type PrivateSessionId string

A private ID, sent by the server at the beginning of the Socket.IO session and used for connection state recovery upon reconnection

type RemoteSocket

type RemoteSocket struct {
	// contains filtered or unexported fields
}

Expose of subset of the attributes and methods of the Socket struct

func MakeRemoteSocket

func MakeRemoteSocket() *RemoteSocket

func NewRemoteSocket

func NewRemoteSocket(adapter Adapter, details SocketDetails) *RemoteSocket

func (*RemoteSocket) Construct

func (r *RemoteSocket) Construct(adapter Adapter, details SocketDetails)

func (*RemoteSocket) Data

func (r *RemoteSocket) Data() any

func (*RemoteSocket) Disconnect

func (r *RemoteSocket) Disconnect(status bool) *RemoteSocket

Disconnects this client.

Param: close - if `true`, closes the underlying connection

func (*RemoteSocket) Emit

func (r *RemoteSocket) Emit(ev string, args ...any) error

func (*RemoteSocket) Handshake

func (r *RemoteSocket) Handshake() *Handshake

func (*RemoteSocket) Id

func (r *RemoteSocket) Id() SocketId

func (*RemoteSocket) Join

func (r *RemoteSocket) Join(room ...Room)

Joins a room.

Param: Room - a Room, or a Room slice to expand

func (*RemoteSocket) Leave

func (r *RemoteSocket) Leave(room ...Room)

Leaves a room.

Param: Room - a Room, or a Room slice to expand

func (*RemoteSocket) Rooms

func (r *RemoteSocket) Rooms() *types.Set[Room]

func (*RemoteSocket) Timeout

func (r *RemoteSocket) Timeout(timeout time.Duration) *BroadcastOperator

Adds a timeout in milliseconds for the next operation.

io.FetchSockets()(func(sockets []*RemoteSocket, _ error){

	for _, socket := range sockets {
		if (someCondition) {
			socket.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
				if err != nil {
					// the client did not acknowledge the event in the given delay
				}
			})
		}
	}

})
// Note: if possible, using a room instead of looping over all sockets is preferable

io.Timeout(1000 * time.Millisecond).To(someConditionRoom).Emit("some-event", func(args []any, err error) {
	// ...
})

Param: time.Duration - timeout

type Room

type Room string

we could extend the Room type to "string", but that would be a breaking change Related: https://github.com/socketio/socket.io-redis-adapter/issues/418

type SeesionData

type SeesionData struct {
	Pid    any `json:"pid" mapstructure:"pid" msgpack:"pid"`
	Offset any `json:"offset" mapstructure:"offset" msgpack:"offset"`
}

func (*SeesionData) GetOffset

func (s *SeesionData) GetOffset() (offset string, ok bool)

func (*SeesionData) GetPid

func (s *SeesionData) GetPid() (pid string, ok bool)

type Server

type Server struct {
	*StrictEventEmitter
	// contains filtered or unexported fields
}

Represents a Socket.IO server.

import (
	"github.com/zishang520/engine.io/v2/utils"
	"github.com/Presslogic-Media/socket.io/v2/socket"
)

io := socket.NewServer(nil, nil)

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)

	utils.Log().Info(`socket %s connected`, socket.Id())

	// send an event to the client
	socket.Emit("foo", "bar")

	socket.On("foobar", func(...any) {
		// an event was received from the client
	})

	// upon disconnection
	socket.On("disconnect", func(reason ...any) {
		utils.Log().Info(`socket %s disconnected due to %s`, socket.Id(), reason[0])
	})
})
io.Listen(3000, nil)

func MakeServer

func MakeServer() *Server

func NewServer

func NewServer(srv any, opts *ServerOptions) *Server

func (*Server) Adapter

func (s *Server) Adapter() AdapterConstructor

func (*Server) AllSockets deprecated

func (s *Server) AllSockets() (*types.Set[SocketId], error)

Gets a list of socket ids.

Deprecated: this method will be removed in the next major release, please use [Server#ServerSideEmit] or [Server#FetchSockets] instead.

func (*Server) Attach

func (s *Server) Attach(srv any, opts *ServerOptions) *Server

Attaches socket.io to a server or port.

Param: srv - server or port

Param: opts - options passed to engine.io

func (*Server) Bind

func (s *Server) Bind(egs engine.BaseServer) *Server

Binds socket.io to an engine.io instance.

Param: engine engine.io (or compatible) server

func (*Server) Close

func (s *Server) Close(fn func(error))

Closes server connection

Param: [fn] optional, called as `fn(error)` on error OR all conns closed

func (*Server) Compress

func (s *Server) Compress(compress bool) *BroadcastOperator

Sets the compress flag.

io.Compress(false).Emit("hello")

Param: bool - if `true`, compresses the sending data

Return: a new BroadcastOperator instance for chaining

func (*Server) ConnectTimeout

func (s *Server) ConnectTimeout() time.Duration

func (*Server) Construct

func (s *Server) Construct(srv any, opts *ServerOptions)

func (*Server) DisconnectSockets

func (s *Server) DisconnectSockets(status bool)

Makes the matching socket instances disconnect

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances disconnect (the connections might be kept alive for other namespaces)
io.DisconnectSockets(false)

// make all socket instances in the "room1" room disconnect and close the underlying connections
io.In("room1").DisconnectSockets(true)

Param: close - whether to close the underlying connection

func (*Server) EmitWithAck

func (s *Server) EmitWithAck(ev string, args ...any) func(func([]any, error))

Emits an event and waits for an acknowledgement from all clients.

io.Timeout(1000 * time.Millisecond).EmitWithAck("some-event")(func(args []any, err error) {
	if err == nil {
		fmt.Println(args) // one response per client
	} else {
		// some servers did not acknowledge the event in the given delay
	}
})

Return: a `func(func([]any, error))` that will be fulfilled when all servers have acknowledged the event

func (*Server) Encoder

func (s *Server) Encoder() parser.Encoder

func (*Server) Engine

func (s *Server) Engine() engine.BaseServer

func (*Server) Except

func (s *Server) Except(room ...Room) *BroadcastOperator

Excludes a room when emitting.

// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
io.Except("room-101").Emit("foo", "bar")

// with an array of rooms
io.Except(["room-101", "room-102"]).Emit("foo", "bar")
io.Except([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
io.Except("room-101").Except("room-102").Emit("foo", "bar")

Param: Room - a Room, or a Room slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Server) FetchSockets

func (s *Server) FetchSockets() func(func([]*RemoteSocket, error))

Returns the matching socket instances

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

io.FetchSockets()(func(sockets []*RemoteSocket, _ error){
	// return all Socket instances
})

// return all Socket instances in the "room1" room
io.In("room1").FetchSockets()(func(sockets []*RemoteSocket, _ error){

	for _, socket := range sockets {
		fmt.Println(socket.Id())
		fmt.Println(socket.Handshake())
		fmt.Println(socket.Rooms())
		fmt.Println(socket.Data())

		socket.Emit("hello")
		socket.Join("room1")
		socket.Leave("room2")
		socket.Disconnect()
	}

})

func (*Server) In

func (s *Server) In(room ...Room) *BroadcastOperator

Targets a room when emitting. Similar to `to()`, but might feel clearer in some cases:

// disconnect all clients in the "room-101" room
io.In("room-101").DisconnectSockets(false)

Param: Room - a Room, or a Room slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Server) Listen

func (s *Server) Listen(srv any, opts *ServerOptions) *Server

Attaches socket.io to a server or port.

Param: srv - server or port

Param: opts - options passed to engine.io

func (*Server) Local

func (s *Server) Local() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.

// the “foo” event will be broadcast to all connected clients on this node
io.Local().Emit("foo", "bar")

Return: a new BroadcastOperator instance for chaining

func (*Server) Of

func (s *Server) Of(name any, fn func(...any)) NamespaceInterface

Looks up a namespace.

// with a simple string
myNamespace := io.Of("/my-namespace")

// with a regex
const dynamicNsp = io.Of(regexp.MustCompile(`^\/dynamic-\d+$`), nil).On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	namespace := socket.Nsp() // newNamespace.Name() === "/dynamic-101"

	// broadcast to all clients in the given sub-namespace
	namespace.Emit("hello")
})

Param: string | *regexp.Regexp | ParentNspNameMatchFn - nsp name

Param: func(...any) - nsp `connection` ev handler

func (*Server) Opts

func (s *Server) Opts() *ServerOptions

func (*Server) Path

func (s *Server) Path() string

Return: self when setting or value when getting

func (*Server) Send

func (s *Server) Send(args ...any) *Server

Sends a `message` event to all clients.

This method mimics the WebSocket.send() method.

See: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send

io.Send("hello")

// this is equivalent to
io.Emit("message", "hello")

func (*Server) ServeClient

func (s *Server) ServeClient() bool

Return: self when setting or value when getting

func (*Server) ServeHandler

func (s *Server) ServeHandler(opts *ServerOptions) http.Handler

Output http.Handler interface

func (*Server) ServerSideEmit

func (s *Server) ServerSideEmit(ev string, args ...any) error

Sends a message to the other Socket.IO servers of the cluster.

io.ServerSideEmit("hello", "world")

io.On("hello", func(args ...any) {
	fmt.Println(args) // prints "world"
})

// acknowledgements (without binary content) are supported too:
io.ServerSideEmit("ping", func(args []any, err error) {
	if err != nil {
		// some servers did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per server (except the current one)
	}
})

io.On("ping", func(args ...any) {
	args[0]("pong")
})

Param: ev - the event name

Param: args - an slice of arguments, which may include an acknowledgement callback at the end

func (*Server) ServerSideEmitWithAck

func (s *Server) ServerSideEmitWithAck(ev string, args ...any) func(func([]any, error))

Sends a message and expect an acknowledgement from the other Socket.IO servers of the cluster.

io.Timeout(1000 * time.Millisecond).ServerSideEmitWithAck("some-event")(func(args []any, err error) {
	if err == nil {
		fmt.Println(args) // one response per client
	} else {
		// some servers did not acknowledge the event in the given delay
	}
})

Param: ev - the event name

Param: args - an array of arguments

Return: a `func(func([]any, error))` that will be fulfilled when all servers have acknowledged the event

func (*Server) SetAdapter

func (s *Server) SetAdapter(v AdapterConstructor) *Server

Sets the adapter for rooms.

Param: v AdapterConstructor interface

func (*Server) SetConnectTimeout

func (s *Server) SetConnectTimeout(v time.Duration) *Server

Set the delay after which a client without namespace is closed

Param: v

func (*Server) SetPath

func (s *Server) SetPath(v string) *Server

Sets the client serving path.

Param: v pathname

func (*Server) SetServeClient

func (s *Server) SetServeClient(v bool) *Server

Sets/gets whether client code is being served.

Param: v - whether to serve client code

func (*Server) Sockets

func (s *Server) Sockets() NamespaceInterface

func (*Server) SocketsJoin

func (s *Server) SocketsJoin(room ...Room)

Makes the matching socket instances join the specified rooms

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances join the "room1" room
io.SocketsJoin("room1")

// make all socket instances in the "room1" room join the "room2" and "room3" rooms
io.In("room1").SocketsJoin([]Room{"room2", "room3"}...)

Param: Room - a Room, or a Room slice to expand

func (*Server) SocketsLeave

func (s *Server) SocketsLeave(room ...Room)

Makes the matching socket instances leave the specified rooms

Note: this method also works within a cluster of multiple Socket.IO servers, with a compatible Adapter.

// make all socket instances leave the "room1" room
io.SocketsLeave("room1")

// make all socket instances in the "room1" room leave the "room2" and "room3" rooms
io.In("room1").SocketsLeave([]Room{"room2", "room3"}...)

Param: Room - a Room, or a Room slice to expand

func (*Server) Timeout

func (s *Server) Timeout(timeout time.Duration) *BroadcastOperator

Adds a timeout in milliseconds for the next operation

io.Timeout(1000 * time.Millisecond).Emit("some-event", func(args []any, err error) {
	if err != nil {
		// some clients did not acknowledge the event in the given delay
	} else {
		fmt.Println(args) // one response per client
	}
})

Param: timeout

func (*Server) To

func (s *Server) To(room ...Room) *BroadcastOperator

Targets a room when emitting.

// the “foo” event will be broadcast to all connected clients in the “room-101” room
io.To("room-101").Emit("foo", "bar")

// with an array of rooms (a client will be notified at most once)
io.To("room-101", "room-102").Emit("foo", "bar")
io.To([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

// with multiple chained calls
io.To("room-101").To("room-102").Emit("foo", "bar")

Param: Room - a Room, or a Room slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Server) Use

func (s *Server) Use(fn func(*Socket, func(*ExtendedError))) *Server

Registers a middleware, which is a function that gets executed for every incoming Socket.

io.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// ...
	next(nil)
})

Param: func(*ExtendedError) - the middleware function

func (*Server) Volatile

func (s *Server) Volatile() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to receive messages (because of network slowness or other issues, or because they’re connected through long polling and is in the middle of a request-response cycle).

io.Volatile().Emit("hello") // the clients may or may not receive it

Return: a new BroadcastOperator instance for chaining

func (*Server) Write

func (s *Server) Write(args ...any) *Server

Sends a `message` event to all clients. Alias of [Send].

type ServerOptions

type ServerOptions struct {
	config.ServerOptions
	config.AttachOptions
	// contains filtered or unexported fields
}

func DefaultServerOptions

func DefaultServerOptions() *ServerOptions

func (*ServerOptions) Adapter

func (s *ServerOptions) Adapter() AdapterConstructor

func (*ServerOptions) Assign

func (*ServerOptions) CleanupEmptyChildNamespaces

func (s *ServerOptions) CleanupEmptyChildNamespaces() bool

func (*ServerOptions) ConnectTimeout

func (s *ServerOptions) ConnectTimeout() time.Duration

func (*ServerOptions) ConnectionStateRecovery

func (s *ServerOptions) ConnectionStateRecovery() *ConnectionStateRecovery

func (*ServerOptions) GetRawAdapter

func (s *ServerOptions) GetRawAdapter() AdapterConstructor

func (*ServerOptions) GetRawCleanupEmptyChildNamespaces

func (s *ServerOptions) GetRawCleanupEmptyChildNamespaces() *bool

func (*ServerOptions) GetRawConnectTimeout

func (s *ServerOptions) GetRawConnectTimeout() *time.Duration

func (*ServerOptions) GetRawConnectionStateRecovery

func (s *ServerOptions) GetRawConnectionStateRecovery() *ConnectionStateRecovery

func (*ServerOptions) GetRawParser

func (s *ServerOptions) GetRawParser() parser.Parser

func (*ServerOptions) GetRawServeClient

func (s *ServerOptions) GetRawServeClient() *bool

func (*ServerOptions) Parser

func (s *ServerOptions) Parser() parser.Parser

func (*ServerOptions) Path

func (s *ServerOptions) Path() string

func (*ServerOptions) ServeClient

func (s *ServerOptions) ServeClient() bool

func (*ServerOptions) SetAdapter

func (s *ServerOptions) SetAdapter(adapter AdapterConstructor)

func (*ServerOptions) SetCleanupEmptyChildNamespaces

func (s *ServerOptions) SetCleanupEmptyChildNamespaces(cleanupEmptyChildNamespaces bool)

func (*ServerOptions) SetConnectTimeout

func (s *ServerOptions) SetConnectTimeout(connectTimeout time.Duration)

func (*ServerOptions) SetConnectionStateRecovery

func (s *ServerOptions) SetConnectionStateRecovery(connectionStateRecovery *ConnectionStateRecovery)

func (*ServerOptions) SetParser

func (s *ServerOptions) SetParser(parser parser.Parser)

func (*ServerOptions) SetServeClient

func (s *ServerOptions) SetServeClient(serveClient bool)

type ServerOptionsInterface

type ServerOptionsInterface interface {
	config.ServerOptionsInterface
	config.AttachOptionsInterface

	SetServeClient(bool)
	GetRawServeClient() *bool
	ServeClient() bool

	SetAdapter(AdapterConstructor)
	GetRawAdapter() AdapterConstructor
	Adapter() AdapterConstructor

	SetParser(parser.Parser)
	GetRawParser() parser.Parser
	Parser() parser.Parser

	SetConnectTimeout(time.Duration)
	GetRawConnectTimeout() *time.Duration
	ConnectTimeout() time.Duration

	SetConnectionStateRecovery(*ConnectionStateRecovery)
	GetRawConnectionStateRecovery() *ConnectionStateRecovery
	ConnectionStateRecovery() *ConnectionStateRecovery

	SetCleanupEmptyChildNamespaces(bool)
	GetRawCleanupEmptyChildNamespaces() *bool
	CleanupEmptyChildNamespaces() bool
}

type Session

type Session struct {
	*SessionToPersist

	MissedPackets []any `json:"missedPackets" mapstructure:"missedPackets" msgpack:"missedPackets"`
}

type SessionAwareAdapterBuilder

type SessionAwareAdapterBuilder struct {
}

func (*SessionAwareAdapterBuilder) New

type SessionToPersist

type SessionToPersist struct {
	Sid   SocketId         `json:"sid" mapstructure:"sid" msgpack:"sid"`
	Pid   PrivateSessionId `json:"pid" mapstructure:"pid" msgpack:"pid"`
	Rooms *types.Set[Room]
	Data  any `json:"data" mapstructure:"data" msgpack:"data"`
}

type SessionWithTimestamp

type SessionWithTimestamp struct {
	*SessionToPersist

	DisconnectedAt int64 `json:"disconnectedAt" mapstructure:"disconnectedAt" msgpack:"disconnectedAt"`
}

type Socket

type Socket struct {
	*StrictEventEmitter
	// contains filtered or unexported fields
}

This is the main object for interacting with a client.

A Socket belongs to a given Namespace and uses an underlying Client to communicate.

Within each Namespace, you can also define arbitrary channels (called "rooms") that the Socket can join and leave. That provides a convenient way to broadcast to a group of socket instances.

io.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)

	utils.Log().Info(`socket %s connected`, socket.Id())

	// send an event to the client
	socket.Emit("foo", "bar")

	socket.On("foobar", func(...any) {
		// an event was received from the client
	})

	// join the room named "room1"
	socket.Join("room1")

	// broadcast to everyone in the room named "room1"
	io.to("room1").Emit("hello")

	// upon disconnection
	socket.On("disconnect", func(reason ...any) {
		utils.Log().Info(`socket %s disconnected due to %s`, socket.Id(), reason[0])
	})
})

func MakeSocket

func MakeSocket() *Socket

func NewSocket

func NewSocket(nsp *Namespace, client *Client, auth any, previousSession *Session) *Socket

func (*Socket) Acks

func (s *Socket) Acks() *types.Map[uint64, func([]any, error)]

func (*Socket) Broadcast

func (s *Socket) Broadcast() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the sender.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// the “foo” event will be broadcast to all connected clients, except this socket
	socket.Broadcast().Emit("foo", "bar")
})

Return: a new [BroadcastOperator] instance for chaining

func (*Socket) Client

func (s *Socket) Client() *Client

func (*Socket) Compress

func (s *Socket) Compress(compress bool) *Socket

Sets the compress flag.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.Compress(false).Emit("hello")
})

Param: compress - if `true`, compresses the sending data

func (*Socket) Conn

func (s *Socket) Conn() engine.Socket

A reference to the underlying Client transport connection (Engine.IO Socket interface).

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	fmt.Println(socket.Conn().Transport().Name()) // prints "polling" or "websocket" or "webtransport"

	socket.Conn().Once("upgrade", func(...any) {
		fmt.Println(socket.Conn().Transport().Name()) // prints "websocket"
	})
})

func (*Socket) Connected

func (s *Socket) Connected() bool

Whether the socket is currently connected or not.

io.Use(func(socket *socket.Socket, next func(*ExtendedError)) {
	fmt.Println(socket.Connected()) // false
	next(nil)
})

io.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	fmt.Println(socket.Connected()) // true
})

func (*Socket) Construct

func (s *Socket) Construct(nsp *Namespace, client *Client, auth any, previousSession *Session)

func (*Socket) Data

func (s *Socket) Data() any

func (*Socket) Disconnect

func (s *Socket) Disconnect(status bool) *Socket

Disconnects this client.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// disconnect this socket (the connection might be kept alive for other namespaces)
	socket.Disconnect(false)

	// disconnect this socket and close the underlying connection
	socket.Disconnect(true)
})

Param: status - if `true`, closes the underlying connection

func (*Socket) Disconnected

func (s *Socket) Disconnected() bool

Whether the socket is currently disconnected

func (*Socket) Emit

func (s *Socket) Emit(ev string, args ...any) error

Emits to this client.

io.On("connection", func(args ...any) {
	socket := args[0].(*socket.Socket)
	socket.Emit("hello", "world")

	// all serializable datastructures are supported (no need to call json.Marshal, But the map can only be of `map[string]any` type, currently does not support other types of maps)
	socket.Emit("hello", 1, "2", map[string]any{"3": []string{"4"}, "5": types.NewBytesBuffer([]byte{6})})

	// with an acknowledgement from the client
	socket.Emit("hello", "world", func(args []any, err error) {
		// ...
	})
})

func (*Socket) EmitWithAck

func (s *Socket) EmitWithAck(ev string, args ...any) func(func([]any, error))

Emits an event and waits for an acknowledgement

io.On("connection", func(args ...any) => {
	client := args[0].(*socket.Socket)
	// without timeout
	client.EmitWithAck("hello", "world")(func(args []any, err error) {
		if err == nil {
			fmt.Println(args) // one response per client
		} else {
			// some clients did not acknowledge the event in the given delay
		}
	})

	// with a specific timeout
	client.Timeout(1000 * time.Millisecond).EmitWithAck("hello", "world")(func(args []any, err error) {
		if err == nil {
			fmt.Println(args) // one response per client
		} else {
			// some clients did not acknowledge the event in the given delay
		}
	})
})

Return: a `func(func([]any, error))` that will be fulfilled when all clients have acknowledged the event

func (*Socket) Except

func (s *Socket) Except(room ...Room) *BroadcastOperator

Excludes a room when broadcasting.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
	// and this socket
	socket.Except("room-101").Emit("foo", "bar")

	// with an array of rooms
	socket.Except([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

	// with multiple chained calls
	socket.Except("room-101").Except("room-102").Emit("foo", "bar")
})

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Socket) Handshake

func (s *Socket) Handshake() *Handshake

The handshake details.

func (*Socket) Id

func (s *Socket) Id() SocketId

An unique identifier for the session.

func (*Socket) In

func (s *Socket) In(room ...Room) *BroadcastOperator

Targets a room when broadcasting. Similar to `to()`, but might feel clearer in some cases:

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// disconnect all clients in the "room-101" room, except this socket
	socket.In("room-101").DisconnectSockets(false)
});

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Socket) Join

func (s *Socket) Join(rooms ...Room)

Joins a room.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// join a single room
	socket.Join("room1")

	// join multiple rooms
	socket.Join([]Room{"room-101", "room-102"}...)
})

Param: Room - a `Room`, or a `Room` slice to expand

func (*Socket) Leave

func (s *Socket) Leave(room Room)

Leaves a room.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// leave a single room
	socket.Leave("room1")

	// leave multiple rooms
	socket.Leave("room-101")
	socket.Leave("room-102")
})

Param: Room - a `Room`, or a `Room` slice to expand

func (*Socket) ListenersAny

func (s *Socket) ListenersAny() []events.Listener

Returns an array of listeners that are listening for any event that is specified. This array can be manipulated, e.g. to remove listeners.

func (*Socket) ListenersAnyOutgoing

func (s *Socket) ListenersAnyOutgoing() []events.Listener

Returns an array of listeners that are listening for any event that is specified. This array can be manipulated, e.g. to remove listeners.

func (*Socket) Local

func (s *Socket) Local() *BroadcastOperator

Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// the “foo” event will be broadcast to all connected clients on this node, except this socket
	socket.Local().Emit("foo", "bar")
})

Return: a new [BroadcastOperator] instance for chaining

func (*Socket) NotifyOutgoingListeners

func (s *Socket) NotifyOutgoingListeners() func(*parser.Packet)

func (*Socket) Nsp

func (s *Socket) Nsp() *Namespace

func (*Socket) OffAny

func (s *Socket) OffAny(listener events.Listener) *Socket

Removes the listener that will be fired when any event is received.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	catchAllListener := func(events ...any) {
		fmt.Println(`got event `, events)
	}

	socket.OnAny(catchAllListener)

	// remove a specific listener
	socket.OffAny(catchAllListener)

	// or remove all listeners
	socket.OffAny(nil)
})

Param: events.Listener

func (*Socket) OffAnyOutgoing

func (s *Socket) OffAnyOutgoing(listener events.Listener) *Socket

Removes the listener that will be fired when any event is sent.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	catchAllListener := func(events ...any) {
		fmt.Println(`sent event `, events)
	}

	socket.OnAnyOutgoing(catchAllListener)

	// remove a specific listener
	socket.OffAnyOutgoing(catchAllListener)

	// or remove all listeners
	socket.OffAnyOutgoing(nil)
})

Param: events.Listener - the catch-all listener

func (*Socket) OnAny

func (s *Socket) OnAny(listener events.Listener) *Socket

Adds a listener that will be fired when any event is received. The event name is passed as the first argument to the callback.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.OnAny(func(events ...any) {
		fmt.Println(`got event `, events)
	})
})

Param: events.Listener

func (*Socket) OnAnyOutgoing

func (s *Socket) OnAnyOutgoing(listener events.Listener) *Socket

Adds a listener that will be fired when any event is sent. The event name is passed as the first argument to the callback.

Note: acknowledgements sent to the client are not included.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.onAnyOutgoing(func(events ...any) {
		fmt.Println(`got event `, events)
	})
})

Param: events.Listener

func (*Socket) PrependAny

func (s *Socket) PrependAny(listener events.Listener) *Socket

Adds a listener that will be fired when any event is received. The event name is passed as the first argument to the callback. The listener is added to the beginning of the listeners array.

Param: events.Listener

func (*Socket) PrependAnyOutgoing

func (s *Socket) PrependAnyOutgoing(listener events.Listener) *Socket

Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the callback. The listener is added to the beginning of the listeners array.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.PrependAnyOutgoing(func(events ...any) {
		fmt.Println(`sent event `, events)
	})
})

func (*Socket) Recovered

func (s *Socket) Recovered() bool

Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will be transmitted to the client, the data attribute and the rooms will be restored.

func (*Socket) Request

func (s *Socket) Request() *types.HttpContext

A reference to the request that originated the underlying Engine.IO Socket.

func (*Socket) Rooms

func (s *Socket) Rooms() *types.Set[Room]

Returns the rooms the socket is currently in.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	fmt.Println(socket.Rooms()) // *types.Set { <socket.id> }

	socket.Join("room1")

	fmt.Println(socket.Rooms()) // *types.Set { <socket.id>, "room1" }
})

func (*Socket) Send

func (s *Socket) Send(args ...any) *Socket

Sends a `message` event.

This method mimics the WebSocket.send() method.

See: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.Send("hello");

	// this is equivalent to
	socket.Emit("message", "hello");
});

func (*Socket) SetData

func (s *Socket) SetData(data any)

Additional information that can be attached to the Socket instance and which will be used in the [Server.fetchSockets()] method.

func (*Socket) Timeout

func (s *Socket) Timeout(timeout time.Duration) *Socket

Sets a modifier for a subsequent event emission that the callback will be called with an error when the given number of milliseconds have elapsed without an acknowledgement from the client:

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.Timeout(1000 * time.Millisecond).Emit("my-event", func(args []any, err error) {
		if err != nil {
			// the client did not acknowledge the event in the given delay
		}
	})
})

func (*Socket) To

func (s *Socket) To(room ...Room) *BroadcastOperator

Targets a room when broadcasting.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	// the “foo” event will be broadcast to all connected clients in the “room-101” room, except this socket
	socket.To("room-101").Emit("foo", "bar")

	// the code above is equivalent to:
	io.To("room-101").Except(Room(socket.Id())).Emit("foo", "bar")

	// with an array of rooms (a client will be notified at most once)
	socket.To([]Room{"room-101", "room-102"}...).Emit("foo", "bar")

	// with multiple chained calls
	socket.To("room-101").To("room-102").Emit("foo", "bar")
})

Param: Room - a `Room`, or a `Room` slice to expand

Return: a new BroadcastOperator instance for chaining

func (*Socket) Use

func (s *Socket) Use(fn func([]any, func(error))) *Socket

Sets up socket middleware.

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.Use(func(events []any, next func(error)) {
		if isUnauthorized(events[0]) {
			next(error.New("unauthorized event"))
			return
		}
		// do not forget to call next
		next(nil)
	})

	socket.On("error", func(errs ...any) {
		if err, ok := errs[0].(error); ok && err.Error() == "unauthorized event" {
			socket.Disconnect(false)
		}
	});
});

Param: fn - middleware function (event, next)

func (*Socket) Volatile

func (s *Socket) Volatile() *Socket

Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to receive messages (because of network slowness or other issues, or because they’re connected through long polling and is in the middle of a request-response cycle).

io.On("connection", func(clients ...any) {
	socket := clients[0].(*socket.Socket)
	socket.Volatile().Emit("hello") // the client may or may not receive it
})

func (*Socket) Write

func (s *Socket) Write(args ...any) *Socket

Sends a `message` event. Alias of Send.

type SocketDetails

type SocketDetails interface {
	Id() SocketId
	Handshake() *Handshake
	Rooms() *types.Set[Room]
	Data() any
}

type SocketId

type SocketId string

A public ID, sent by the server at the beginning of the Socket.IO session and which can be used for private messaging

type StrictEventEmitter

type StrictEventEmitter struct {
	events.EventEmitter
}

Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type parameters for mappings of event names to event data types, and strictly types method calls to the `EventEmitter` according to these event maps.

func NewStrictEventEmitter

func NewStrictEventEmitter() *StrictEventEmitter

func (*StrictEventEmitter) Emit

func (s *StrictEventEmitter) Emit(ev string, args ...any)

Emits an event.

Param: ev Name of the event

Param: args Values to send to listeners of this event

func (*StrictEventEmitter) EmitReserved

func (s *StrictEventEmitter) EmitReserved(ev string, args ...any)

Emits a reserved event.

This method is `protected`, so that only a class extending `StrictEventEmitter` can emit its own reserved events.

Param: ev Reserved event name

Param: args Arguments to emit along with the event

func (*StrictEventEmitter) EmitUntyped

func (s *StrictEventEmitter) EmitUntyped(ev string, args ...any)

Emits an event.

This method is `protected`, so that only a class extending `StrictEventEmitter` can get around the strict typing. This is useful for calling `emit.apply`, which can be called as `emitUntyped.apply`.

Param: ev Event name

Param: args Arguments to emit along with the event

func (*StrictEventEmitter) Listeners

func (s *StrictEventEmitter) Listeners(ev string) []events.Listener

Returns the listeners listening to an event.

Param: event Event name

Returns: Slice of listeners subscribed to `event`

func (*StrictEventEmitter) On

func (s *StrictEventEmitter) On(ev string, listeners ...events.Listener) error

Adds the `listener` function as an event listener for `ev`.

Param: ev Name of the event

Param: listener Callback function

func (*StrictEventEmitter) Once

func (s *StrictEventEmitter) Once(ev string, listeners ...events.Listener) error

Adds a one-time `listener` function as an event listener for `ev`.

Param: ev Name of the event

Param: listener Callback function

type WriteOptions

type WriteOptions struct {
	packet.Options

	Volatile   bool `json:"volatile" mapstructure:"volatile" msgpack:"volatile"`
	PreEncoded bool `json:"preEncoded" mapstructure:"preEncoded" msgpack:"preEncoded"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL