device

package
v0.9.0-alpha Latest Latest
Warning

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

Go to latest
Published: Feb 1, 2017 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultDeviceNameHeader = "X-Webpa-Device-Name"
	DefaultConveyHeader     = "X-Webpa-Convey"

	DefaultHandshakeTimeout time.Duration = 10 * time.Second
	DefaultIdlePeriod       time.Duration = 135 * time.Second
	DefaultWriteTimeout     time.Duration = 60 * time.Second
	DefaultPingPeriod       time.Duration = 45 * time.Second

	DefaultInitialCapacity        = 100000
	DefaultReadBufferSize         = 4096
	DefaultWriteBufferSize        = 4096
	DefaultDeviceMessageQueueSize = 100
)
View Source
const (
	// DeviceManagerKey is the Viper subkey under which device.Options are typically stored
	// In a JSON configuration file, this will be expressed as:
	//
	//   {
	//     /* other stuff can be here */
	//
	//     "device": {
	//       "manager": {
	//       }
	//     }
	//   }
	DeviceManagerKey = "device.manager"
)

Variables

This section is empty.

Functions

func EncodeConvey

func EncodeConvey(convey Convey, encoding *base64.Encoding) (string, error)

EncodeConvey transforms a Convey map into its on-the-wire representation, using the supplied encoding. If encoding == nil, base64.StdEncoding is used.

func IDHashParser

func IDHashParser(deviceNameHeader string) func(*http.Request) ([]byte, error)

IDHashParser creates a parsing function that examines an HTTP request to produce a []byte key for consistent hashing. The returned function examines the given request header and invokes ParseID on the value.

If deviceNameHeader is the empty string, DefaultDeviceNameHeader is used.

func NewConnectHandler

func NewConnectHandler(manager Manager, responseHeader http.Header, logger logging.Logger) http.Handler

NewConnectHandler produces an http.Handler that allows devices to connect to a specific Manager.

func NewDeviceListHandler

func NewDeviceListHandler(manager Manager, logger logging.Logger) http.Handler

NewDeviceListHandler returns an http.Handler that renders a JSON listing of the devices within a manager.

Types

type ConnectListener

type ConnectListener func(Interface)

ConnectListener is a function which receives notifications when devices successfully connect to the system.

func ConnectListeners

func ConnectListeners(listeners ...ConnectListener) ConnectListener

ConnectListeners aggregates multiple listeners into one. If this method is passed zero (0) listeners, an internal default is used instead.

type Connection

type Connection interface {
	io.Closer

	// Read returns the next WRP message frame.  If this method returns an error,
	// this connection should be abandoned and closed.  This method is not safe
	// for concurrent invocation and must not be invoked concurrently with Write().
	//
	// Both the raw data frame (a byte slice) and the decoded message are returned.  This
	// allows for efficient transfers, since calling code can choose to simply hand the byte
	// slice off rather than re-encoding the message.
	//
	// Read may skip frames if they are not supported by the WRP protocol.  For example,
	// text frames are not supported and are skipped.  Anytime a frame is skipped, this
	// method returns a nil message with a nil error.
	Read() ([]byte, *wrp.Message, error)

	// Write sends a WRP frame to the device.  If this method returns an error,
	// this connection should be abandoned and closed.  This method is not safe
	// for concurrent invocation and must not be invoked concurrently with Read().
	Write(*wrp.Message) error

	// Ping sends a ping message to the device.  This method may be invoked concurrently
	// with any other method of this interface, including Ping() itself.
	Ping([]byte) error

	// SetPongCallback registers the given function to be invoked whenever this connection
	// notices a pong from the device.  Note that this is not the same as a handler.  This callback
	// cannot return an error, and is invoked as part of the internal pong handler that
	// enforces the idle policy.  The pong callback can be nil, which simply reverts back
	// to the internal default handler.
	//
	// This method cannot be called concurrently with Write().
	SetPongCallback(func(string))

	// SendClose transmits a close frame to the device.  After this method is invoked,
	// the only method that should be invoked is Close()
	SendClose() error
}

Connection represents a websocket connection to a WebPA-compatible device. Connection implementations abstract the semantics of serverside WRP message handling and enforce policies like idleness.

type ConnectionFactory

type ConnectionFactory interface {
	NewConnection(http.ResponseWriter, *http.Request, http.Header) (Connection, error)
}

ConnectionFactory provides the instantiation logic for Connections. This interface is appropriate for server-side connections that enforce various WebPA policies, such as idleness and a write timeout.

func NewConnectionFactory

func NewConnectionFactory(o *Options) ConnectionFactory

NewConnectionFactory produces a ConnectionFactory instance from a set of Options.

type Convey

type Convey map[string]interface{}

Convey represents an arbitrary block of JSON that should be transmitted in HTTP requests related to devices. It is typically sent via a header as base64-encoded JSON.

func ParseConvey

func ParseConvey(value string, encoding *base64.Encoding) (Convey, error)

ParseConvey decodes a value using the supplied encoding and then unmarshals the result as a Convey map. If encoding is nil, base64.StdEncoding is used.

type DeviceError

type DeviceError interface {
	error
	ID() ID
	Key() Key
}

DeviceError is the common interface implemented by all error objects which carry device-related metadata

func NewBusyError

func NewBusyError(id ID, key Key) DeviceError

func NewClosedError

func NewClosedError(id ID, key Key) DeviceError

func NewDuplicateKeyError

func NewDuplicateKeyError(key Key) DeviceError

func NewMissingIDError

func NewMissingIDError(id ID) DeviceError

func NewMissingKeyError

func NewMissingKeyError(key Key) DeviceError

type Dialer

type Dialer interface {
	Dial(URL string, id ID, convey Convey, extra http.Header) (Connection, *http.Response, error)
}

Dialer is a WebPA dialer for websocket Connections

func NewDialer

func NewDialer(o *Options, d *websocket.Dialer) Dialer

NewDialer constructs a WebPA Dialer using a set of Options and a gorilla Dialer. Both parameters are optional. If the gorilla Dialer is supplied, it is copied for use internally. If an Options is supplied, the appropriate settings will override any gorilla Dialer, e.g. ReadBufferSize.

type DisconnectListener

type DisconnectListener func(Interface)

DisconnectListener is a function which receives notifications when devices disconnect (or, are disconnected) from the system

func DisconnectListeners

func DisconnectListeners(listeners ...DisconnectListener) DisconnectListener

DisconnectListeners aggregates multiple listeners into one. If this method is passed zero (0) listeners, an internal default is used instead.

type ID

type ID string

ID represents a normalized identifer for a device.

func IntToMAC

func IntToMAC(value uint64) ID

IntToMAC accepts a 64-bit integer and formats that as a device MAC address identifier The returned ID will be of the form mac:XXXXXXXXXXXX, where X is a hexadecimal digit using lowercased letters.

func ParseID

func ParseID(deviceName string) (ID, error)

ParseID parses a raw device name into a canonicalized identifier.

func (ID) Bytes

func (id ID) Bytes() []byte

Bytes is a convenience function to obtain the []byte representation of an ID.

type Interface

type Interface interface {
	// ID returns the canonicalized identifer for this device.  Note that
	// this is NOT globally unique.  It is possible for multiple devices
	// with the same ID to be connected.  This typically occurs due to fraud,
	// but we don't want to turn away duped devices.
	ID() ID

	// Key returns the current unique key for this device.
	Key() Key

	// Convey returns the payload to convey with each web-bound request
	Convey() Convey

	// ConnectedAt returns the time at which this device connected to the system
	ConnectedAt() time.Time

	// RequestClose posts a request for this device to be disconnected.  This method
	// is asynchronous and idempotent.  If this method is invoked when a shutdown
	// request has already been queued or when this device is already shut down, this
	// method returns an error.
	RequestClose()

	// Closed tests if this device is closed.  When this method returns true,
	// any attempt to send messages to this device will result in an error.
	//
	// Once closed, a device cannot be reopened.
	Closed() bool

	// Send dispatches a message to this device.  This method is useful outside
	// a Manager if multiple messages should be sent to the device.
	//
	// This method will return an error if this device has been closed or
	// if the device is busy and cannot accept more messages.
	Send(*wrp.Message) error
}

Interface is the core type for this package. It provides access to public device metadata and the ability to send messages directly the a device.

Instances are mostly immutable, and have a strict lifecycle. Devices are initially open, and when closed cannot be reused or reopened. A new device instance is required if further communication is desired after the original device instance is closed.

The only piece of metadata that is mutable is the Key. A device Manager allows clients to change the routing Key of a device. All other public metadata is immutable.

type Key

type Key string

Key is a routing identifier for a device. While multiple devices in a Manager can have the same ID, Keys are unique to specific devices.

type KeyFunc

type KeyFunc func(ID, Convey, *http.Request) (Key, error)

KeyFunc returns the unique Key for a device at the point of connection.

func UUIDKeyFunc

func UUIDKeyFunc(source io.Reader, encoding *base64.Encoding) KeyFunc

UUIDKeyFunc produces a KeyFunc which creates type 4 UUIDs for device Keys.

If source == nil, then rand.Reader from crypto/rand is used. If encoding == nil, then base64.RawURLEncoding is used.

type Manager

type Manager interface {
	// Connect upgrade an HTTP connection to a websocket and begins concurrent
	// managment of the device.
	Connect(http.ResponseWriter, *http.Request, http.Header) (Interface, error)

	// Disconnect disconnects all devices (including duplicates) which connected
	// with the given ID.  This method returns the number of devices disconnected,
	// which can be zero or a positive integer.  Multiple devices are permitted with
	// the same ID, and this method disconnects all duplicate devices associated with that ID.
	Disconnect(ID) int

	// DisconnectOne disconnects the single device associated with the given Key.  This method
	// returns the count of devices disconnected, which will be zero (0) if no device existed
	// or one (1) if there was a device with that key.
	DisconnectOne(Key) int

	// DisconnectIf iterates over all devices known to this manager, applying the
	// given predicate.  For any devices that result in true, this method disconnects them.
	// Note that this method may pause connections and disconnections while it is executing.
	// This method returns the number of devices that were disconnected.
	//
	// Only disconnection by ID is supported, which means that any identifier matching
	// the predicate will result in *all* duplicate devices under that ID being removed.
	//
	// No methods on this Manager should be called from within the predicate function, or
	// a deadlock will likely occur.
	DisconnectIf(func(ID) bool) int

	// VisitIf applies a visitor to any device matching the ID predicate.
	//
	// No methods on this Manager should be called from within either the predicate
	// or the visitor, or a deadlock will most definitely occur.
	VisitIf(func(ID) bool, func(Interface)) int

	// VisitAll applies the given visitor function to each device known to this manager.
	//
	// No methods on this Manager should be called from within the visitor function, or
	// a deadlock will likely occur.
	VisitAll(func(Interface)) int

	// Send dispatches a message to all devices registered with the given canonical ID.
	// An optional callback can be supplied to allow the caller to receive information
	// for each send attempt.  This callback will be invoked for each send, successes
	// being indicated by a nil error.
	//
	// No methods on this Manager should be called from within the callback function, or
	// a deadlock will likely occur.
	Send(ID, *wrp.Message, func(Interface, error)) error

	// SendOne attempts to send a message to the single, unique device identified by the Key.
	SendOne(Key, *wrp.Message) error
}

Manager supplies a hub for connecting and disconnecting devices as well as an access point for obtaining device metadata.

func NewManager

func NewManager(o *Options, cf ConnectionFactory) Manager

NewManager constructs a Manager from a set of options. A ConnectionFactory will be created from the options if one is not supplied.

type MessageListener

type MessageListener func(Interface, []byte, *wrp.Message)

MessageListener represents a sink for device messages

func MessageListeners

func MessageListeners(listeners ...MessageListener) MessageListener

MessageListeners aggregates multiple listeners into one. If this method is passed zero (0) listeners, an internal default is used instead.

type Options

type Options struct {
	// DeviceNameHeader is the name of the HTTP request header which contains the
	// device name.  If not specified, DefaultDeviceNameHeader is used.
	DeviceNameHeader string

	// ConveyHeader is the name of the HTTP request header which contains the
	// base64-encoded JSON payload to forward with each outbound device request.
	// If not specified, DefaultConveyHeader is used.
	ConveyHeader string

	// HandshakeTimeout is the optional websocket handshake timeout.  If not supplied,
	// the internal gorilla default is used.
	HandshakeTimeout time.Duration

	// InitialCapacity is used as the starting capacity of the internal map of
	// registered devices.  If not supplied, DefaultInitialCapacity is used.
	InitialCapacity int

	// ReadBufferSize is the optional size of websocket read buffers.  If not supplied,
	// the internal gorilla default is used.
	ReadBufferSize int

	// WriteBufferSize is the optional size of websocket write buffers.  If not supplied,
	// the internal gorilla default is used.
	WriteBufferSize int

	// Subprotocols is the optional slice of websocket subprotocols to use.
	Subprotocols []string

	// DeviceMessageQueueSize is the capacity of the channel which stores messages waiting
	// to be transmitted to a device.  If not supplied, DefaultDeviceMessageQueueSize is used.
	DeviceMessageQueueSize int

	// PingPeriod is the time between pings sent to each device
	PingPeriod time.Duration

	// IdlePeriod is the length of time a device connection is allowed to be idle,
	// with no traffic coming from the device.  If not supplied, DefaultIdlePeriod is used.
	IdlePeriod time.Duration

	// WriteTimeout is the write timeout for each device's websocket.  If not supplied,
	// DefaultWriteTimeout is used.
	WriteTimeout time.Duration

	// MessageListener is the notification sink for device messages
	MessageListener MessageListener

	// ConnectListener receives notifications for device connections
	ConnectListener ConnectListener

	// DisconnectListener receives notifications when devices disconnect for any reason
	DisconnectListener DisconnectListener

	// PongListener is the notification sink for pongs
	PongListener PongListener

	// KeyFunc is the factory function for Keys, used when devices connect.
	// If this value is nil, then UUIDKeyFunc is used along with crypto/rand's Reader.
	KeyFunc KeyFunc

	// Logger is the output sink for log messages.  If not supplied, log output
	// is sent to logging.DefaultLogger().
	Logger logging.Logger
}

Options represent the available configuration options for device Managers and ConnectionFactories.

func NewOptions

func NewOptions(logger logging.Logger, v *viper.Viper) (o *Options, err error)

NewOptions unmarshals a device.Options from a Viper environment. Listeners must be configured separately.

type PongListener

type PongListener func(Interface, string)

PongListener is a function which receives notifications when devices disconnect (or, are disconnected) from the system

func PongListeners

func PongListeners(listeners ...PongListener) PongListener

PongListeners aggregates multiple listeners into one. If this method is passed zero (0) listeners, an internal default is used instead.

Jump to

Keyboard shortcuts

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