gosocketio

package module
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2024 License: MIT Imports: 12 Imported by: 0

README

golang socket.io GoDoc

golang socket.io is an implementation for the socket.io protocol in Go. There is a lack of specification for the socket.io protocol, so reverse engineering is the easiest way to find out how it works.

This is a work in progress. Many features, such as middleware and binary support, are missing.

golang socket.io is an adapted work from github.com/graarh/golang-socketio.

on "connection", "error", and "disconnection"

socket.io has three special events it triggers on the client-side and you should not emit them on your own programs.

Wait for the socket.io connection event before emitting messages or you risk losing them due in an unpredictable fashion (due to concurrency: connection latency, server load, etc.). For the default namespace this is automatically handled on gosocketio.Connect.

However, before emitting a message on a custom namespace, you want to wait for the ready signal, like so:

ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()

select {
	case <-ctx.Done():
		return ctx.Err()
	case <-exampleNamespace.Ready():
		// don't need to do anything
}

if err := exampleNamespace.Emit("fleet", 100); err != nil {
	return err
}

The reason why you probably want to use a select receiving a second channel, such as context.Done() on all non-trivial programs is to avoid program loop, leak memory, or both in case of failure.

The default namespace is automatically ready after establishing the socket.io session. Therefore, *gosocketio.Client doesn't expose a Ready() method.

Connecting to a socket.io server with a custom namespace

You can connect to a namespace and start emitting messages to it with:

c, err := gosocketio.Connect(u, websocket.NewTransport())

if err != nil {
	return err
}

// ...

exampleNamespace, err := c.Of("example")	

If err != nil {
	return err
}

<-exampleNamespace.Ready() // don't do this, use a select like shown above instead!

If err := exampleNamespace.Emit("list", "friends"); err != nil {
	return err
}

Running the example

  1. npm install to install the dependencies for the example server
  2. node server.js
  3. go run example.go

If you need to improve this library you should consider using these tools:

This library is used by the WeDeploy Command-Line Interface tool to open a shell and execute commands on Docker container services.

Documentation

Index

Constants

View Source
const (
	// OnConnection for "connection" messages.
	OnConnection = protocol.OnConnection

	// OnDisconnect for "disconnect" messages.
	OnDisconnect = protocol.OnDisconnect

	// OnError for "error" messages.
	OnError = protocol.OnError
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client to handle socket.io connections

func ConnectSync

func ConnectSync(u url.URL, tr *websocket.Transport) (c *Client, err error)

Connect dials and waits for the "connection" event. It blocks for the timeout duration. If the connection is not established in time, it closes the connection and returns an error.

func DialOnly

func DialOnly(u url.URL, tr *websocket.Transport) (c *Client, err error)

DialOnly connects to the host and initializes the socket.io protocol. It doesn't wait for socket.io connection handshake. You probably want to use Connect instead. Only exposed for debugging.

func (*Client) Ack

func (c *Client) Ack(ctx context.Context, method string, args interface{}, ret interface{}) error

Ack packet based on given data and send it and receive response

func (*Client) Close

func (c *Client) Close()

Close client connection

func (*Client) Emit

func (c *Client) Emit(method string, args ...interface{}) error

Emit message

func (*Client) ID

func (c *Client) ID() string

ID of current socket connection

func (*Client) Listeners

func (c *Client) Listeners() (list []string)

Listeners on the default namespace

func (*Client) Of

func (c *Client) Of(namespace string) (*Namespace, error)

Of subscribes to a namespace

func (*Client) Off

func (c *Client) Off(method string)

Off unregisters a listener

func (*Client) On

func (c *Client) On(method string, f interface{}) error

On registers a handler

func (*Client) Run

func (c *Client) Run()

type ErrorArgument

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

ErrorArgument is used when trying to create a non-function listener with an invalid parameter

func (ErrorArgument) Error

func (e ErrorArgument) Error() string

type ErrorInvalidInterface

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

func (ErrorInvalidInterface) Error

func (e ErrorInvalidInterface) Error() string

func (ErrorInvalidInterface) Method

func (e ErrorInvalidInterface) Method() string

type ErrorNotFunction

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

ErrorNotFunction is used when trying to create a non-function listener

func (ErrorNotFunction) Error

func (e ErrorNotFunction) Error() string

type Handler

type Handler struct {
	Func reflect.Value

	Out      bool
	Variadic bool
	// contains filtered or unexported fields
}

Handler for the message

func NewHandler

func NewHandler(f interface{}) (*Handler, error)

NewHandler creates a new listener

func (*Handler) Args

func (h *Handler) Args() []interface{}

Args returns the interfaces for the given function

func (*Handler) Call

func (h *Handler) Call(args ...interface{}) []reflect.Value

Call function

type Header struct {
	Sid          string   `json:"sid"`
	Upgrades     []string `json:"upgrades"`
	PingInterval int      `json:"pingInterval"`
	PingTimeout  int      `json:"pingTimeout"`
}

Header of engine.io to send and receive packets

type Namespace

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

Namespace for the connection.

func NewNamespace

func NewNamespace(c *Client, namespace string) *Namespace

NewNamespace creates a namespace.

func (*Namespace) Ack

func (n *Namespace) Ack(ctx context.Context, method string, args interface{}, v interface{}) error

Ack packet based on given data and send it and receive response.

func (*Namespace) Emit

func (n *Namespace) Emit(method string, args ...interface{}) error

Emit message.

func (*Namespace) Listeners

func (n *Namespace) Listeners() (list []string)

Listeners on a namespace.

func (*Namespace) Off

func (n *Namespace) Off(method string)

Off unregisters a listener.

func (*Namespace) On

func (n *Namespace) On(method string, f interface{}) error

On registers a listener.

func (*Namespace) Ready

func (n *Namespace) Ready() <-chan struct{}

Ready returns a channel that informs whether the namespace is already connected. It is a more idiomatic Go way to do 'on "connection"'.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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