sockets

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 24, 2015 License: MIT Imports: 11 Imported by: 12

README

sockets wercker status

Sockets to channels binding for martini.

API Reference

Description

Package sockets makes it fun to use websockets with Martini. Its aim is to provide an easy to use interface for socket handling which makes it possible to implement socket messaging with just one select statement listening to different channels.

JSON

sockets.JSON is a simple middleware that organizes websockets messages into any struct type you may wish for.

Messages

sockets.Messages is a simple middleware that organizes websockets messages into string channels.

Usage

Have a look into the example directory to get a feeling for how to use the sockets package.

This package essentially provides a binding of websockets to channels, which you can use as in the following, contrived example:

m.Get("/", sockets.JSON(Message{}), func(params martini.Params, receiver <-chan *Message, sender chan<- *Message, done <-chan bool, disconnect chan<- int, errorChannel <-chan error) {
	ticker = time.After(30 * time.Minute)
	for {
		select {
		case msg := <-receiver:
			// here we simply echo the received message to the sender for demonstration purposes
			// In your app, collect the senders of different clients and do something useful with them
			sender <- msg
		case <- ticker:
			// This will close the connection after 30 minutes no matter what
			// To demonstrate use of the disconnect channel
			// You can use close codes according to RFC 6455
			disconnect <- websocket.CloseNormalClosure
		case <-client.done:
			// the client disconnected, so you should return / break if the done channel gets sent a message
			return
		case err := <-errorChannel:
			// Uh oh, we received an error. This will happen before a close if the client did not disconnect regularly.
			// Maybe useful if you want to store statistics
		}
	}
})

For a simple string messaging connection with string channels, use sockets.Message()

Options

You can configure the options for sockets by passing in sockets.Options as the second argument to sockets.JSON or as the first argument to sockets.Message. Use it to configure the following options (defaults are used here):

&sockets.Options{
	// The logger to use for socket logging
	Logger: log.New(os.Stdout, "[sockets] ", 0), // *log.Logger

	// The LogLevel for socket logging, possible values:
	// sockets.LogLevelError (0)
	// sockets.LogLevelWarning (1)
	// sockets.LogLevelInfo (2)
	// sockets.LogLevelDebug (3)
	
	LogLevel: sockets.LogLevelInfo, // int
	
	// Set to true if you want to skip logging
	SkipLogging: false // bool

	// The time to wait between writes before timing out the connection
	// When this is a zero value time instance, write will never time out
	WriteWait: 60 * time.Second, // time.Duration

	// The time to wait at maximum between receiving pings from the client.
	PongWait: 60 * time.Second, // time.Duration

	// The time to wait between sending pings to the client
	// Attention, this does have to be shorter than PongWait and WriteWait
	// unless you want connections to constantly time out.
	PingPeriod: (60 * time.Second * 8 / 10), // time.Duration

	// The maximum messages size for receiving and sending in bytes
	// Messages bigger than this will lead to panic and disconnect
	MaxMessageSize 65536 // int64

	// The send channel buffer
	// How many messages can be asynchronously held before the channel blocks
	SendChannelBuffer 10 // int

	// The receiving channel buffer
	// How many messages can be asynchronously held before the channel blocks
	RecvChannelBuffer 10 // int

	// The allowed origin
	// Must be compileable as regexp. {{host}} will be replaced with the current
	// request host if given. 
	AllowedOrigin "https?://{{host}}$" // string
}

Rundown

Since it augments the level of websocket handling, it may prove useful if you know how this package does the channel mapping. Here's the rundown for a connection lifetime:

  1. Request Method (must be GET) and origin (can not be cross-origin) are tested. If any of these conditions fail, a HTTP status is returned accordingly and the next handler is ignored.

  2. The request is upgraded to a websocket connection. If this fails, http.StatusBadRequest is returned and the next handler is ignored.

  3. The connection and its channels are created according to given options and mapped for dependency injection in martini.

  4. Three goroutines are started: One is waiting on the websocket for messages, another is waiting for messages from the next handler and occasionally pinging the client. The third is waiting for disconnection coming from both sides. All these goroutines are closed with the websocket, which is also why you should not try to send messages to a client after an error occurred.

  5. On the event of a disconnection sent either by the next handler or via the websocket or when an error occurs, the connection is closed with an appropriate or a given closing message.

gorilla vs go.net websockets

The gorilla websocket package is a brilliant implementation of RFC 6455 compliant websockets which has these advantages over the go.net implementation..

FAQ

  • Q: I am getting this error when compiling: context.Set undefined (type martini.Context has no field or method Set)

    A: This package depends on a recently updated version of the inject package - update this package and the error should vanish.

Authors

Documentation

Overview

The sockets package implements a middleware for standard websocket handling in Martini using the RFC 6455 compliant gorilla implementation of the websocket protocol (github.com/gorilla/websocket). It maps the websocket connection to channels and takes care of connection setup and destruction in order to facilitate easier setup & use of websocket connections.

Index

Constants

View Source
const (
	// Log levels 0-4. Use to set the log level you wish to go for
	LogLevelError   = 0
	LogLevelWarning = 1
	LogLevelInfo    = 2
	LogLevelDebug   = 3
)

Variables

View Source
var LogLevelStrings = []string{"Error", "Warning", "Info", "Debug"}

Log Level to strings slice

Functions

func JSON

func JSON(bindStruct interface{}, options ...*Options) martini.Handler

JSON returns a websocket handling middleware. It can only be used in handlers for HTTP GET. IMPORTANT: The last handler in your handler chain must block in order for the connection to be kept alive. It accepts an empty struct it will copy and try to populate with data received from the client using the JSON Marshaler, as well as it will serialize your structs to JSON and send them to the client. For the following, it is assumed you passed a struct named Message to the handler. It maps four channels for you to use in the follow-up Handler(s):

  • A receiving string channel (<-chan *Message) on which you will receive all incoming structs from the client
  • A sending string channel (chan<- *Message) on which you will be able to send structs to the client.
  • A receiving error channel (<-chan error) on which you will receive errors occurring while sending & receiving
  • A receiving disconnect channel (<-chan bool) on which you will receive a message only if the connection is about to be closed following an error or a client disconnect.
  • A sending done channel (chan<- bool) on which you can send as soon as you wish to disconnect the connection.

The middleware handles the following for you: - Checking the request for cross origin access - Doing the websocket handshake - Setting sensible options for the Gorilla websocket connection - Starting and terminating the necessary goroutines An optional sockets.Options object can be passed to Messages to overwrite default options mentioned in the documentation of the Options object.

func Messages

func Messages(options ...*Options) martini.Handler

Messages returns a websocket handling middleware. It can only be used in handlers for HTTP GET. IMPORTANT: The last handler in your handler chain must block in order for the connection to be kept alive. It maps four channels for you to use in the follow-up Handler(s):

  • A receiving string channel (<-chan string) on which you will receive all incoming strings from the client
  • A sending string channel (chan<- string) on which you will be able to send strings to the client.
  • A receiving error channel (<-chan error) on which you will receive errors occurring while sending & receiving
  • A receiving disconnect channel (<-chan bool) on which you will receive a message only if the connection is about to be closed following an error or a client disconnect.
  • A sending done channel (chan<- bool) on which you can send as soon as you wish to disconnect the connection.

The middleware handles the following for you: - Checking the request for cross origin access - Doing the websocket handshake - Setting sensible options for the Gorilla websocket connection - Starting and terminating the necessary goroutines An optional sockets.Options object can be passed to Messages to overwrite default options mentioned in the documentation of the Options object.

Types

type Binding

type Binding interface {
	Close(int) error

	DisconnectChannel() chan int
	ErrorChannel() chan error
	// contains filtered or unexported methods
}

type Connection

type Connection struct {
	*Options

	// The error channel is given the error object as soon as an error occurs
	// either sending or receiving values from the websocket. This channel gets
	// mapped for the next handler to use.
	Error chan error

	// The disconnect channel is for listening for disconnects from the next handler.
	// Any sends to the disconnect channel lead to disconnecting the socket with the
	// given closing message. This channel gets mapped for the next
	// handler to use.
	Disconnect chan int

	// The done channel gets called only when the connection
	// has been successfully disconnected. Any sends to the disconnect
	// channel are currently ignored. This channel gets mapped for the next
	// handler to use.
	Done chan bool
	// contains filtered or unexported fields
}

func (*Connection) Close

func (c *Connection) Close(closeCode int) error

Close the Base connection. Closes the send Handler and all channels used Since all channels are either internal or channels this middleware is sending on.

func (*Connection) DisconnectChannel

func (c *Connection) DisconnectChannel() chan int

func (*Connection) ErrorChannel

func (c *Connection) ErrorChannel() chan error

type JSONConnection

type JSONConnection struct {
	*Connection

	// Sender is the channel used for sending out JSON to the client.
	// This channel gets mapped for the next handler to use with the right type
	// and is asynchronous unless the SendChannelBuffer is set to 0.
	Sender reflect.Value

	// Receiver is the string channel used for receiving JSON from the client.
	// This channel gets mapped for the next handler to use with the right type
	// and is asynchronous unless the RecvChannelBuffer is set to 0.
	Receiver reflect.Value
}

Message Connection connects a websocket message connection to a reflect.Value channel.

func (*JSONConnection) Close

func (c *JSONConnection) Close(closeCode int) error

Close the JSON connection. Closes the send goroutine and all channels used Except for the send channel, since it should be closed by the handler sending on it.

type MessageConnection

type MessageConnection struct {
	*Connection

	// Sender is the string channel used for sending out strings to the client.
	// This channel gets mapped for the next handler to use and is asynchronous
	// unless the SendChannelBuffer is set to 0.
	Sender chan string

	// Receiver is the string channel used for receiving strings from the client.
	// This channel gets mapped for the next handler to use and is asynchronous
	// unless the RecvChannelBuffer is set to 0.
	Receiver chan string
}

Message Connection connects a websocket message connection to a string channel.

func (*MessageConnection) Close

func (c *MessageConnection) Close(closeCode int) error

Close the Message connection. Closes the send goroutine and all channels used Except for the send channel, since it should be closed by the handler sending on it.

type Options

type Options struct {
	// The logger to use for socket logging
	Logger *log.Logger

	// The LogLevel for socket logging, goes from 0 (Error) to 3 (Debug)
	LogLevel int

	// Set to true if you want to skip logging
	SkipLogging bool

	// The time to wait between writes before timing out the connection
	// When this is a zero value time instance, write will never time out
	WriteWait time.Duration

	// The time to wait at maximum between receiving pings from the client.
	PongWait time.Duration

	// The time to wait between sending pings to the client
	PingPeriod time.Duration

	// The maximum messages size for receiving and sending in bytes
	MaxMessageSize int64

	// The send channel buffer
	SendChannelBuffer int

	// The receiving channel buffer
	RecvChannelBuffer int

	// Allowed origins for websocket connections
	AllowedOrigin string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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