ss

package module
v0.0.0-...-508e9f6 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2018 License: MIT Imports: 14 Imported by: 7

README

Sacrificial-Socket GoDoc

A Go server library and pure JS client library for managing communication between websockets, that has an API similar to Socket.IO, but feels less... well, Javascripty. Socket.IO is great, but nowadays all modern browsers support websockets natively, so in most cases there is no need to have websocket simulation fallbacks like XHR long polling or Flash. Removing these allows Sacrificial-Socket to be lightweight and very performant.

Sacrificial-Socket supports rooms, roomcasts, broadcasts, and event emitting just like Socket.IO, but with one key difference. The data passed into event functions is not an interface{} that is implied to be a string or map[string]interface{}, but is always passed in as a []byte making it easier to unmarshal into your own JSON data structs, convert to a string, or keep as binary data without the need to check the data's type before processing it. It also means there aren't any unnecessary conversions to the data between the client and the server.

Sacrificial-Socket also has a MultihomeBackend interface for syncronizing broadcasts and roomcasts across multiple instances of Sacrificial-Socket running on multiple machines. Out of the box Sacrificial-Socket provides a MultihomeBackend interface for the popular noSQL database MongoDB, one for the moderately popular key/value storage engine Redis, and one for the not so popular GRPC protocol, for syncronizing instances on multiple machines.

In depth examples can be found in the examples directory.

Usage

Client Javascript:
(function(SS){ 'use strict';
    var ss = new SS('ws://localhost:8080/socket');
    ss.onConnect(function(){
        ss.emit('echo', 'hello echo!');
    });
    
    ss.on('echo', function(data){
        alert('got echo:', data);
        ss.close();
    });
    
    ss.onDisconnect(function(){
        console.log('socket connection closed');
    });
})(window.SS);
Server Go:
package main

import(
    "net/http"
    ss "github.com/raz-varren/sacrificial-socket"
)

func doEcho(s *ss.Socket, data []byte) {
    s.Emit("echo", string(data))
}

func main() {
    s := ss.NewServer()
    s.On("echo", doEcho)
    
    http.Handle("/socket", s)
    http.ListenAndServe(":8080", nil);
}

Documentation

Overview

Package ss (Sacrificial-Socket) is a Go server library and pure JS client library for managing communication between websockets, that has an API similar to Socket.IO, but feels less... well, Javascripty. Socket.IO is great, but nowadays all modern browsers support websockets natively, so in most cases there is no need to have websocket simulation fallbacks like XHR long polling or Flash. Removing these allows Sacrificial-Socket to be lightweight and very performant.

Sacrificial-Socket supports rooms, roomcasts, broadcasts, and event emitting just like Socket.IO, but with one key difference. The data passed into event functions is not an interface{} that is implied to be a string or map[string]interface{}, but is always passed in as a []byte making it easier to unmarshal into your own JSON data structs, convert to a string, or keep as binary data without the need to check the data's type before processing it. It also means there aren't any unnecessary conversions to the data between the client and the server.

Sacrificial-Socket also has a MultihomeBackend interface for syncronizing broadcasts and roomcasts across multiple instances of Sacrificial-Socket running on multiple machines. Out of the box Sacrificial-Socket provides a MultihomeBackend interface for the popular noSQL database MongoDB, one for the moderately popular key/value storage engine Redis, and one for the not so popular GRPC protocol, for syncronizing instances on multiple machines.

Index

Examples

Constants

View Source
const (

	//SubProtocol is the official sacrificial-socket sub protocol
	SubProtocol string = "sac-sock"
)

Variables

This section is empty.

Functions

func DefaultUpgrader

func DefaultUpgrader() *websocket.Upgrader

DefaultUpgrader returns a websocket upgrader suitable for creating sacrificial-socket websockets.

Types

type BroadcastMsg

type BroadcastMsg struct {
	EventName string
	Data      interface{}
}

BroadcastMsg represents an event to be dispatched to all Sockets on the SocketServer

type EventHandler

type EventHandler interface {
	HandleEvent(*Socket, []byte)
	EventName() string
}

EventHandler is an interface for registering events using SockerServer.OnEvent

type MultihomeBackend

type MultihomeBackend interface {
	//Init is called as soon as the MultihomeBackend is
	//registered using SocketServer.SetMultihomeBackend
	Init()

	//Shutdown is called immediately after all sockets have
	//been closed
	Shutdown()

	//BroadcastToBackend is called everytime a BroadcastMsg is
	//sent by a Socket
	//
	//BroadcastToBackend must be safe for concurrent use by multiple
	//go routines
	BroadcastToBackend(*BroadcastMsg)

	//RoomcastToBackend is called everytime a RoomMsg is sent
	//by a socket, even if none of this server's sockets are
	//members of that room
	//
	//RoomcastToBackend must be safe for concurrent use by multiple
	//go routines
	RoomcastToBackend(*RoomMsg)

	//BroadcastFromBackend is called once and only once as a go routine as
	//soon as the MultihomeBackend is registered using
	//SocketServer.SetMultihomeBackend
	//
	//b consumes a BroadcastMsg and dispatches
	//it to all sockets on this server
	BroadcastFromBackend(b chan<- *BroadcastMsg)

	//RoomcastFromBackend is called once and only once as a go routine as
	//soon as the MultihomeBackend is registered using
	//SocketServer.SetMultihomeBackend
	//
	//r consumes a RoomMsg and dispatches it to all sockets
	//that are members the specified room
	RoomcastFromBackend(r chan<- *RoomMsg)
}

MultihomeBackend is an interface for implementing a mechanism to syncronize Broadcasts and Roomcasts to multiple SocketServers running separate machines.

Sacrificial-Socket provides a MultihomeBackend for use with MongoDB in sacrificial-socket/backend

type RNG

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

RNG is a random number generator that is safe for concurrent use by multiple go routines

func NewRNG

func NewRNG() *RNG

NewRNG creates a new random number generator

func (*RNG) Read

func (r *RNG) Read(b []byte) (int, error)

Read reads len(b) random bytes into b and always returns a nil error

type RoomMsg

type RoomMsg struct {
	RoomName  string
	EventName string
	Data      interface{}
}

RoomMsg represents an event to be dispatched to a room of sockets

type Socket

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

Socket represents a websocket connection

func (*Socket) Broadcast

func (s *Socket) Broadcast(eventName string, data interface{})

Broadcast dispatches an event to all Sockets on the SocketServer.

func (*Socket) Close

func (s *Socket) Close()

Close closes the Socket connection and removes the Socket from any rooms that it was a member of

func (*Socket) Emit

func (s *Socket) Emit(eventName string, data interface{}) error

Emit dispatches an event to s.

func (*Socket) GetRooms

func (s *Socket) GetRooms() []string

GetRooms returns a list of rooms that s is a member of

func (*Socket) ID

func (s *Socket) ID() string

ID returns the unique ID of s

func (*Socket) InRoom

func (s *Socket) InRoom(roomName string) bool

InRoom returns true if s is currently a member of roomName

func (*Socket) Join

func (s *Socket) Join(roomName string)

Join adds s to the specified room. If the room does not exist, it will be created

func (*Socket) Leave

func (s *Socket) Leave(roomName string)

Leave removes s from the specified room. If s is not a member of the room, nothing will happen. If the room is empty upon removal of s, the room will be closed

func (*Socket) Roomcast

func (s *Socket) Roomcast(roomName, eventName string, data interface{})

Roomcast dispatches an event to all Sockets in the specified room.

func (*Socket) Socketcast

func (s *Socket) Socketcast(socketID, eventName string, data interface{})

Socketcast dispatches an event to the specified socket ID.

type SocketServer

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

SocketServer manages the coordination between sockets, rooms, events and the socket hub

func NewServer

func NewServer() *SocketServer

NewServer creates a new instance of SocketServer

Example
package main

import (
	"encoding/json"
	"github.com/raz-varren/sacrificial-socket"
	"log"
	"net/http"
	"os"
)

func main() {
	serv := ss.NewServer()
	serv.On("echo", Echo)
	serv.On("join", Join)
	serv.On("leave", Leave)
	serv.On("roomcast", Roomcast)
	serv.On("broadcast", Broadcast)

	done := make(chan bool)

	go func() {
		serv.EnableSignalShutdown(done)
		<-done
		os.Exit(0)
	}()

	http.Handle("/socket", s)
	log.Fatalln(http.ListenAndServe(":8080", nil))
}

type JoinJSON struct {
	Room string
}

type LeaveJSON struct {
	Room string
}

type RoomcastJSON struct {
	Room, Event, Data string
}

type BroadcastJSON struct {
	Event, Data string
}

func Echo(s *ss.Socket, data []byte) {
	s.Emit("echo", string(data))
}

func Join(s *ss.Socket, data []byte) {
	var j JoinJSON
	err := json.Unmarshal(data, &j)
	check(err)

	s.Join(j.Room)
	s.Emit("echo", "joined: "+j.Room)
}

func Leave(s *ss.Socket, data []byte) {
	var l LeaveJSON
	err := json.Unmarshal(data, &l)
	check(err)

	s.Leave(l.Room)
	s.Emit("echo", "left: "+l.Room)
}

func Broadcast(s *ss.Socket, data []byte) {
	var b BroadcastJSON
	err := json.Unmarshal(data, &b)
	check(err)

	s.Broadcast(b.Event, b.Data)
}

func Roomcast(s *ss.Socket, data []byte) {
	var r RoomcastJSON
	err := json.Unmarshal(data, &r)
	check(err)

	s.Roomcast(r.Room, r.Event, r.Data)
}

func check(err error) {
	if err != nil {
		log.Fatalln(err)
	}
}
Output:

func (*SocketServer) Broadcast

func (serv *SocketServer) Broadcast(eventName string, data interface{})

Broadcast dispatches an event to all Sockets on the SocketServer.

func (*SocketServer) EnableSignalShutdown

func (serv *SocketServer) EnableSignalShutdown(complete chan<- bool)

EnableSignalShutdown listens for linux syscalls SIGHUP, SIGINT, SIGTERM, SIGQUIT, SIGKILL and calls the SocketServer.Shutdown() to perform a clean shutdown. true will be passed into complete after the Shutdown proccess is finished

func (*SocketServer) On

func (serv *SocketServer) On(eventName string, handleFunc func(*Socket, []byte))

On registers event functions to be called on individual Socket connections when the server's socket receives an Emit from the client's socket.

Any event functions registered with On, must be safe for concurrent use by multiple go routines

func (*SocketServer) OnConnect

func (serv *SocketServer) OnConnect(handleFunc func(*Socket))

OnConnect registers an event function to be called whenever a new Socket connection is created

func (*SocketServer) OnDisconnect

func (serv *SocketServer) OnDisconnect(handleFunc func(*Socket))

OnDisconnect registers an event function to be called as soon as a Socket connection is closed

func (*SocketServer) OnEvent

func (serv *SocketServer) OnEvent(h EventHandler)

OnEvent has the same functionality as On, but accepts an EventHandler interface instead of a handler function.

func (*SocketServer) Roomcast

func (serv *SocketServer) Roomcast(roomName, eventName string, data interface{})

Roomcast dispatches an event to all Sockets in the specified room.

func (*SocketServer) ServeHTTP

func (serv *SocketServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will upgrade a http request to a websocket using the sac-sock subprotocol

func (*SocketServer) SetMultihomeBackend

func (serv *SocketServer) SetMultihomeBackend(b MultihomeBackend)

SetMultihomeBackend registers a MultihomeBackend interface and calls it's Init() method

func (*SocketServer) SetUpgrader

func (serv *SocketServer) SetUpgrader(u *websocket.Upgrader)

SetUpgrader sets the websocket.Upgrader used by the SocketServer.

func (*SocketServer) Shutdown

func (serv *SocketServer) Shutdown() bool

Shutdown closes all active sockets and triggers the Shutdown() method on any MultihomeBackend that is currently set.

func (*SocketServer) Socketcast

func (serv *SocketServer) Socketcast(socketID, eventName string, data interface{})

Socketcast dispatches an event to the specified socket ID.

func (*SocketServer) WebHandler

func (serv *SocketServer) WebHandler() http.Handler

WebHandler returns a http.Handler to be passed into http.Handle

Depricated: The SocketServer struct now satisfies the http.Handler interface, use that instead

Directories

Path Synopsis
backend
ssdummy
Package ssdummy is a mockup multihome backend.
Package ssdummy is a mockup multihome backend.
ssgrpc
Package ssgrpc provides a ss.MultihomeBackend interface that uses grpc with profobufs for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
Package ssgrpc provides a ss.MultihomeBackend interface that uses grpc with profobufs for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
ssgrpc/token
Package token is used by package ssgrpc for generating and validating HMAC-SHA256 tokens sent as "per RPC credentials".
Package token is used by package ssgrpc for generating and validating HMAC-SHA256 tokens sent as "per RPC credentials".
ssgrpc/transport
Package transport is a generated protocol buffer package.
Package transport is a generated protocol buffer package.
ssmongo
Package ssmongo provides a ss.MultihomeBackend interface that uses MongoDB for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
Package ssmongo provides a ss.MultihomeBackend interface that uses MongoDB for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
ssredis
Package ssredis provides a ss.MultihomeBackend interface that uses Redis for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
Package ssredis provides a ss.MultihomeBackend interface that uses Redis for synchronizing broadcasts and roomcasts between multiple Sacrificial Socket instances.
examples
not-so-simple-examples/grpc-multihome
A complex web app example that implements ssgrpc for synchronizing multiple Sacrificial Socket instances
A complex web app example that implements ssgrpc for synchronizing multiple Sacrificial Socket instances
not-so-simple-examples/redis-multihome
A complex web app example that implements ssredis for synchronizing multiple Sacrificial Socket instances
A complex web app example that implements ssredis for synchronizing multiple Sacrificial Socket instances
simple-examples/chat
A simple web chat app example that does not implement any multihome backends.
A simple web chat app example that does not implement any multihome backends.

Jump to

Keyboard shortcuts

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