glue

package module
v0.0.0-...-06de07e Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2019 License: MIT Imports: 15 Imported by: 28

README

Glue - Robust Go and Javascript Socket Library

GoDoc Go Report Card

Glue is a real-time bidirectional socket library. It is a clean, robust and efficient alternative to socket.io. This library is designed to connect webbrowsers with a go-backend in a simple way. It automatically detects supported socket layers and chooses the most suitable one. This library handles automatic reconnections on disconnections and handles caching to bridge those disconnections. The server implementation is thread-safe and stable. The API is fixed and there won't be any breaking API changes.

Socket layers

Currently two socket layers are supported:

  • WebSockets - This is the primary option. They are used if the webbrowser supports WebSockets defined by RFC 6455.
  • AjaxSockets - This socket layer is used as a fallback mode.

Support

Feel free to contribute to this project. Please check the TODO file for more information.

Install

Client

The client javascript Glue library is located in client/dist/glue.js.

You can use bower to install the client library:

bower install --save glue-socket

Server

Get the source and start hacking.

go get github.com/desertbit/glue

Import it with:

import "github.com/desertbit/glue"

Documentation

Client - Javascript Library

A simple call to glue() without any options will establish a socket connection to the same host. A glue socket object is returned.

// Create and connect to the server.
// Optional pass a host string and options.
var socket = glue();

Optional Javascript options which can be passed to Glue:

var host = "https://foo.bar";

var opts = {
    // The base URL is appended to the host string. This value has to match with the server value.
    baseURL: "/glue/",

    // Force a socket type.
    // Values: false, "WebSocket", "AjaxSocket"
    forceSocketType: false,

    // Kill the connect attempt after the timeout.
    connectTimeout:  10000,

    // If the connection is idle, ping the server to check if the connection is stil alive.
    pingInterval:           35000,
    // Reconnect if the server did not response with a pong within the timeout.
    pingReconnectTimeout:   5000,

    // Whenever to automatically reconnect if the connection was lost.
    reconnect:          true,
    reconnectDelay:     1000,
    reconnectDelayMax:  5000,
    // To disable set to 0 (endless).
    reconnectAttempts:  10,

    // Reset the send buffer after the timeout.
    resetSendBufferTimeout: 10000
};

// Create and connect to the server.
// Optional pass a host string and options.
var socket = glue(host, opts);

The glue socket object has following public methods:

// version returns the glue socket protocol version.
socket.version();

// type returns the current used socket type as string.
// Either "WebSocket" or "AjaxSocket".
socket.type();

// state returns the current socket state as string.
// Following states are available:
//  - "disconnected"
//  - "connecting"
//  - "reconnecting"
//  - "connected"
socket.state();

// socketID returns the socket's ID.
// This is a cryptographically secure pseudorandom number.
socket.socketID();

// send a data string to the server.
// One optional discard callback can be passed.
// It is called if the data could not be send to the server.
// The data is passed as first argument to the discard callback.
// returns:
//  1 if immediately send,
//  0 if added to the send queue and
//  -1 if discarded.
socket.send(data, discardCallback);

// onMessage sets the function which is triggered as soon as a message is received.
socket.onMessage(f);

// on binds event functions to events.
// This function is equivalent to jQuery's on method syntax.
// Following events are available:
//  - "connected"
//  - "connecting"
//  - "disconnected"
//  - "reconnecting"
//  - "error"
//  - "connect_timeout"
//  - "timeout"
//  - "discard_send_buffer"
socket.on();

// Reconnect to the server.
// This is ignored if the socket is not disconnected.
// It will reconnect automatically if required.
socket.reconnect();

// close the socket connection.
socket.close();

// channel returns the given channel object specified by name
// to communicate in a separate channel than the default one.
socket.channel(name);

A channel object has following public methods:

// onMessage sets the function which is triggered as soon as a message is received.
c.onMessage(f);

// send a data string to the channel.
// One optional discard callback can be passed.
// It is called if the data could not be send to the server.
// The data is passed as first argument to the discard callback.
// returns:
//  1 if immediately send,
//  0 if added to the send queue and
//  -1 if discarded.
c.send(data, discardCallback);
Server - Go Library

Check the Documentation at GoDoc.org.

Use a custom HTTP multiplexer

If you choose to use a custom HTTP multiplexer, then it is possible to deactivate the automatic HTTP handler registration of glue.

// Create a new glue server without configuring and starting the HTTP server.
server := glue.NewServer(glue.Options{
    HTTPSocketType: HTTPSocketTypeNone,
})

//...

The glue server implements the ServeHTTP method of the HTTP Handler interface of the http package. Use this to register the glue HTTP handler with a custom multiplexer. Be aware, that the URL of the custom HTTP handler has to match with the glue HTTPHandleURL options string.

Reading data

Data has to be read from the socket and each channel. If you don't require to read data from the socket or a channel, then discard received data with the DiscardRead() method. If received data is not discarded, then the read buffer will block as soon as it is full, which will also block the keep-alive mechanism of the socket. The result would be a closed socket...

// ...

// Discard received data from the main socket channel.
// Hint: Channels have to be discarded separately.
s.DiscardRead()

// ...

// Create a channel.
c := s.Channel("golang")

// Discard received data from a channel.
c.DiscardRead()
Bind custom values to a socket

The socket.Value interface is a placeholder for custom data.

type CustomValues struct {
    Foo string
    Bar int
}

// ...

s.Value = &CustomValues{
    Foo: "Hello World",
    Bar: 900,
}

// ...

v, ok := s.Value.(*CustomValues)
if !ok {
    // Handle error
    return
}
Channels

Channels are separate communication channels from the client to the server of a single socket connections. Multiple separate communication channels can be created:

Server:

// ...

// Create a channel.
c := s.Channel("golang")

// Set the channel on read event function.
c.OnRead(func(data string) {
    // ...
})

// Write to the channel.
c.Write("Hello Gophers!")

Client:

var c = socket.channel("golang");

c.onMessage(function(data) {
    console.log(data);
});

c.send("Hello World");
Broadcasting Messages

With Glue it is easy to broadcast messages to multiple clients. The Glue Server keeps track of all active connected client sessions. You can make use of the server Sockets, GetSocket or OnNewSocket methods to implement broadcasting.

Example

This socket library is very straightforward to use. Check the sample directory for more examples.

Client
<script>
    // Create and connect to the server.
    // Optional pass a host string and options.
    var socket = glue();

    socket.onMessage(function(data) {
        console.log("onMessage: " + data);

        // Echo the message back to the server.
        socket.send("echo: " + data);
    });


    socket.on("connected", function() {
        console.log("connected");
    });

    socket.on("connecting", function() {
        console.log("connecting");
    });

    socket.on("disconnected", function() {
        console.log("disconnected");
    });

    socket.on("reconnecting", function() {
        console.log("reconnecting");
    });

    socket.on("error", function(e, msg) {
        console.log("error: " + msg);
    });

    socket.on("connect_timeout", function() {
        console.log("connect_timeout");
    });

    socket.on("timeout", function() {
        console.log("timeout");
    });

    socket.on("discard_send_buffer", function() {
        console.log("some data could not be send and was discarded.");
    });
</script>
Server

Read data from the socket with a read event function. Check the sample directory for other ways of reading data from the socket.

import (
    "log"
    "net/http"

    "github.com/desertbit/glue"
)

func main() {
    // Create a new glue server.
    server := glue.NewServer(glue.Options{
        HTTPListenAddress: ":8080",
    })

    // Release the glue server on defer.
    // This will block new incoming connections
    // and close all current active sockets.
    defer server.Release()

    // Set the glue event function to handle new incoming socket connections.
    server.OnNewSocket(onNewSocket)

    // Run the glue server.
    err := server.Run()
    if err != nil {
        log.Fatalf("Glue Run: %v", err)
    }
}

func onNewSocket(s *glue.Socket) {
    // Set a function which is triggered as soon as the socket is closed.
    s.OnClose(func() {
        log.Printf("socket closed with remote address: %s", s.RemoteAddr())
    })

    // Set a function which is triggered during each received message.
    s.OnRead(func(data string) {
        // Echo the received data back to the client.
        s.Write(data)
    })

    // Send a welcome string to the client.
    s.Write("Hello Client")
}

Similar Go Projects

  • go-socket.io - socket.io library for golang, a realtime application framework.

Documentation

Overview

Package glue - Robust Go and Javascript Socket Library. This library is thread-safe.

Index

Constants

View Source
const (
	// Version holds the Glue Socket Protocol Version as string.
	// This project follows the Semantic Versioning (http://semver.org/).
	Version = "1.9.1"
)

Public ######

Variables

View Source
var (
	ErrSocketClosed = errors.New("the socket connection is closed")
	ErrReadTimeout  = errors.New("the read timeout was reached")
)

Public errors:

Functions

This section is empty.

Types

type Channel

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

A Channel is a separate communication channel.

func (*Channel) DiscardRead

func (c *Channel) DiscardRead()

DiscardRead ignores and discars the data received from this channel. Call this method during initialization, if you don't read any data from this channel. If received data is not discarded, then the read buffer will block as soon as it is full, which will also block the keep-alive mechanism of the socket. The result would be a closed socket...

func (*Channel) OnRead

func (c *Channel) OnRead(f OnReadFunc)

OnRead sets the function which is triggered if new data is received on the channel. If this event function based method of reading data from the socket is used, then don't use the socket Read method. Either use the OnRead or the Read approach.

func (*Channel) Read

func (c *Channel) Read(timeout ...time.Duration) (string, error)

Read the next message from the channel. This method is blocking. One variadic argument sets a timeout duration. If no timeout is specified, this method will block forever. ErrSocketClosed is returned, if the socket connection is closed. ErrReadTimeout is returned, if the timeout is reached.

func (*Channel) Socket

func (c *Channel) Socket() *Socket

Socket returns the channel's socket.

func (*Channel) Write

func (c *Channel) Write(data string)

Write data to the channel.

type ClosedChan

type ClosedChan <-chan struct{}

ClosedChan is a channel which doesn't block as soon as the socket is closed.

type HTTPSocketType

type HTTPSocketType int

A HTTPSocketType defines which socket type to use for the HTTP glue server.

const (
	// HTTPSocketTypeNone defines to not configure and run a HTTP server.
	HTTPSocketTypeNone HTTPSocketType = 1 << iota

	// HTTPSocketTypeTCP defines to use a TCP server.
	HTTPSocketTypeTCP HTTPSocketType = 1 << iota

	// HTTPSocketTypeUnix defines to use a Unix socket server.
	HTTPSocketTypeUnix HTTPSocketType = 1 << iota
)

type OnCloseFunc

type OnCloseFunc func()

OnCloseFunc is an event function.

type OnNewSocketFunc

type OnNewSocketFunc func(s *Socket)

OnNewSocketFunc is an event function.

type OnReadFunc

type OnReadFunc func(data string)

OnReadFunc is an event function.

type Options

type Options struct {
	// HTTPSocketType defines which socket type to use for the HTTP glue server.
	// Default: HTTPSocketTypeTCP
	HTTPSocketType HTTPSocketType

	// The HTTP address to listen on.
	// Default: ":80"
	HTTPListenAddress string

	// HTTPHandleURL defines the base url to handle glue HTTP socket requests.
	// This has to be set, even if the none socket type is used.
	// Default: "/glue/"
	HTTPHandleURL string

	// CheckOrigin returns true if the request Origin header is acceptable. If
	// CheckOrigin is nil, the host in the Origin header must not be set or
	// must match the host of the request.
	// This method is used by the backend sockets before establishing connections.
	CheckOrigin func(r *http.Request) bool

	// Enables the Cross-Origin Resource Sharing (CORS) mechanism.
	// This will set the Access-Control-Allow-Origin HTTP headers.
	// A resource makes a cross-origin HTTP request when it requests a resource
	// from a different domain than the one which served itself.
	EnableCORS bool
}

Options holds the glue server options.

func (*Options) SetDefaults

func (o *Options) SetDefaults()

SetDefaults sets unset option values to its default value.

type Server

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

A Server represents a glue server which handles incoming socket connections.

func NewServer

func NewServer(o ...Options) *Server

NewServer creates a new glue server instance. One variadic arguments specifies the server options.

func (*Server) Block

func (s *Server) Block(b bool)

Block new incomming connections.

func (*Server) GetSocket

func (s *Server) GetSocket(id string) *Socket

GetSocket obtains a socket by its ID. Returns nil if not found.

func (*Server) IsBlocked

func (s *Server) IsBlocked() bool

IsBlocked returns a boolean whenever new incoming connections should be blocked.

func (*Server) OnNewSocket

func (s *Server) OnNewSocket(f OnNewSocketFunc)

OnNewSocket sets the event function which is triggered if a new socket connection was made. The event function must not block! As soon as the event function returns, the socket is added to the active sockets map.

func (*Server) Release

func (s *Server) Release()

Release this package. This will block all new incomming socket connections and close all current connected sockets.

func (*Server) Run

func (s *Server) Run() error

Run starts the server and listens for incoming socket connections. This is a blocking method.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the HTTP Handler interface of the http package.

func (*Server) Sockets

func (s *Server) Sockets() []*Socket

Sockets returns a list of all current connected sockets. Hint: Sockets are added to the active sockets list before the OnNewSocket event function is called. Use the IsInitialized flag to determind if a socket is not ready yet...

type Socket

type Socket struct {
	// A Value is a placeholder for custom data.
	// Use this to attach socket specific data.
	Value interface{}
	// contains filtered or unexported fields
}

A Socket represents a single socket connections to a client.

func (*Socket) Channel

func (s *Socket) Channel(name string) *Channel

Channel returns the corresponding channel value specified by the name. If no channel value exists for the given name, a new channel is created. Multiple calls to Channel with the same name, will always return the same channel value pointer.

func (*Socket) Close

func (s *Socket) Close()

Close the socket connection.

func (*Socket) ClosedChan

func (s *Socket) ClosedChan() ClosedChan

ClosedChan returns a channel which is non-blocking (closed) as soon as the socket is closed.

func (*Socket) DiscardRead

func (s *Socket) DiscardRead()

DiscardRead ignores and discars the data received from the client. Call this method during initialization, if you don't read any data from the socket. If received data is not discarded, then the read buffer will block as soon as it is full, which will also block the keep-alive mechanism of the socket. The result would be a closed socket...

func (*Socket) ID

func (s *Socket) ID() string

ID returns the socket's unique ID. This is a cryptographically secure pseudorandom number.

func (*Socket) IsClosed

func (s *Socket) IsClosed() bool

IsClosed returns a boolean whenever the connection is closed.

func (*Socket) IsInitialized

func (s *Socket) IsInitialized() bool

IsInitialized returns a boolean indicating if a socket is initialized and ready to be used. This flag is set to true after the OnNewSocket function has returned for this socket.

func (*Socket) OnClose

func (s *Socket) OnClose(f OnCloseFunc)

OnClose sets the functions which is triggered if the socket connection is closed. This method can be called multiple times to bind multiple functions.

func (*Socket) OnRead

func (s *Socket) OnRead(f OnReadFunc)

OnRead sets the function which is triggered if new data is received. If this event function based method of reading data from the socket is used, then don't use the socket Read method. Either use the OnRead or the Read approach.

func (*Socket) Read

func (s *Socket) Read(timeout ...time.Duration) (string, error)

Read the next message from the socket. This method is blocking. One variadic argument sets a timeout duration. If no timeout is specified, this method will block forever. ErrSocketClosed is returned, if the socket connection is closed. ErrReadTimeout is returned, if the timeout is reached.

func (*Socket) RemoteAddr

func (s *Socket) RemoteAddr() string

RemoteAddr returns the remote address of the client.

func (*Socket) UserAgent

func (s *Socket) UserAgent() string

UserAgent returns the user agent of the client.

func (*Socket) Write

func (s *Socket) Write(data string)

Write data to the client.

Directories

Path Synopsis
Package backend provides the server backend with various socket implementations.
Package backend provides the server backend with various socket implementations.
closer
Emit a close function only once, also if called multiple times.
Emit a close function only once, also if called multiple times.
global
Package global provides global types and constants for the backend packages.
Package global provides global types and constants for the backend packages.
sockets/ajaxsocket
Package ajaxsocket provides the ajax socket implementation.
Package ajaxsocket provides the ajax socket implementation.
Package log holds the log backend used by the socket library.
Package log holds the log backend used by the socket library.
sample
Package utils provides utilities for the glue socket implementation.
Package utils provides utilities for the glue socket implementation.

Jump to

Keyboard shortcuts

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