ezmesh

package module
v0.0.0-...-fa109e8 Latest Latest
Warning

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

Go to latest
Published: Apr 16, 2017 License: Zlib Imports: 6 Imported by: 0

README

ezmesh

GoDoc

ezmesh is a lightweight, user-friendly mesh networking library built on top of github.com/weaveworks/mesh.

It provides a minimal interface focused on message-passing (and not maintaining a shared state). It handles the routing for messages to be sent peer-to-peer or from a single peer to all the peers in a network. There's no external dependencies, as the underlying library has been vendored.

This library is in a fairly early stage of development. Please don't use it in production (or even critical development) environments. The underlying library is well-used, however, so it is unlikely to cause a total network meltdown.

I think.

Usage

To join the mesh, call ezmesh.New(), and pass in a Config. The returned Peer represents the connection to the mesh network.

The Peer's Broadcast and Send methods send a message to all other peers in the network or a single peer, respectively.

If the Peer's OnBroadcast and OnMessage fields are populated, they will be called when the Peer receives a brodcast or unicast (i.e. peer-to-peer) message, respectively.

Example

package main

import (
	"log"
	"net"
	"os"

	"github.com/magisterquis/ezmesh"
)

func main() {
	/* Make a PeerName, which uniquely identifies this Peer */
	pn, err := ezmesh.RandomPeerName()
	if nil != err {
		/* Handle error */
	}

	/* Initial Peer to which to connect, can be more than one */
	ip, err := net.ResolveTCPAddr("tcp", "192.168.0.1:3333")
	if nil != err {
		/* Handle error */
	}

	/* Configuration */
	conf := ezmesh.Config{
		Address:      "0.0.0.0",
		Port:         3333,
		Key:          []byte("kittens"),
		AutoConnect:  true,
		ConnLimit:    64,
		NickName:     "examplepeer",
		Name:         &pn,
		InitialPeers: []*net.TCPAddr{ip},
		OnMessage: func(
			p *ezmesh.Peer,
			src ezmesh.PeerName,
			message []byte,
		) error {
			nn, ok := p.NickNameFromPeerName(src)
			if !ok {
				nn = "unknown"
			}
			log.Printf("%v (%v): %q", nn, src, message)
			return nil
		},
		OnBroadcast: func(
			p *ezmesh.Peer,
			src ezmesh.PeerName,
			message []byte,
		) error {
			nn, ok := p.NickNameFromPeerName(src)
			if !ok {
				nn = "unknown"
			}
			log.Printf("Broadcast %v (%v): %q", nn, src, message)
			return nil
		},
	}

	/* Join the mesh network */
	peer, errs, err := ezmesh.New(
		conf,
		log.New(os.Stdout, "[meshdebug] ", log.LstdFlags),
	)
	if nil != err {
		/* Handle error */
	}
	if nil != errs {
		/* Handle connection errors */
	}

	/* Send a hello every so often */
	for {
		/* Say hello to everybody */
		peer.Broadcast([]byte("Hello!"))

		/* Send the controller a message, if he's there */
		if cn, ok := peer.PeerNameFromNickName("controller"); ok {
			peer.Send(cn, []byte("Hello, controller"))
		}
	}
}

Two example programs are provided in ./examples which together form a minimal adminisration system (or a really chatty backdoor). Please don't use them in production, as they're not very robust or secure.

Config

Several parameters need to be set before joining the network, which are passed to New in a struct. Unfortunately, not all of the fields in the struct can be left to default values.

Address and Port

If the address is set, a listener will be started on the given address and port which will accept connections from other peers.

Key

A shared secret common to all members of the mesh network.

AutoConnect

If true, connections will be attepmted to other members of the mesh network besides the initial connections. This improves robustness at the cost of extra comms on the wire.

ConnLimit

Limits the number of connections made.

NickName

The human-friendly name for the Peer in the mesh network. All members of the mesh network have one, which can be retreived using the PeerName as a key with Peer's NickNameFromPeerName() method.

Name

The PeerName for the Peer. See the PeerName section.

InitialPeers

A slice of *net.TCPAddrs to which to make the initial connections to the mesh network. The []error returned from New() indicates any errors connecting to these addresses. If the length of the []error is the number of the initial peers, no connections were made.

OnMessage

Callback function which will be called when a unicast (i.e. peer-to-peer) message is received. The first argument to the function is the local Peer, i.e. not the peer in the mesh network which sent the message. The sending peer is identified by the second argument. If OnMessage is nil, incoming unicast messages will be discarded.

OnBroadcast

Similar to OnMessage, but called for broadcast (i.e. peer-to-everybody) messages.

PeerName

Every member of the mesh network is identified by a unique PeerName, which is an 8-byte number, of which 6 are used by the underlying library.

These may be generated from a MAC address with PeerNameFromMACAddr(), randomly with RandomPeerName(), by hashing a string with PeerNameFromStringHash(), or from a hex-digits-and-colon string (like a MAC address) with UnstringPeerName(). This is a somewhat awkward interface, and is likely to be fixed in the future (without breaking existing code).

A mesh network peer's human-readable NickName may be retreived by calling Peer's NickNameFromPeerName() method, if the peer is known. Likewise, Peer's PeerNameFromNickName() method does the reverse lookup.

It's not a bad idea to try to make sure NickNameFromPeerName()'s second return value is true before sending a message with Peer's Send() method, especially right after joining, to make sure the message has a path to the recipient. There's an example of this in the example program commander.

Documentation

Overview

Package ezmesh wraps github.com/weaveworks/mesh into a more user-friendly library

Index

Constants

View Source
const PROTOVERSION = 2

PROTOVERSION is the protocol version used by this package.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Address and Port specify the IP address and port on which to listen
	// for connections from other peers.  The address may be the empty
	// string, in which case a listener won't be started.
	Address string
	Port    uint16

	// Key provides an encryption key which must be the same for all peers.
	Key []byte

	// AutoConnect controls whether or not connections are automatically
	// attempted to other peers.
	AutoConnect bool

	// ConnLimit specifies the maximum number of peer connections.  A value
	// <= 0 allows unlimited connections.
	ConnLimit int

	// Nickname is the human-friendly name by which this peer will be known.
	NickName string

	// Name is the 8-byte name which represents this peer.  It is common
	// to use a MAC address (via PeerNameFromHardwareAddr).  If Name is
	// nil, it will be generated from NickName.
	Name *PeerName

	// InitialPeers is a slice of addresses containing other peers to which
	// to connect.  This slice may be empty.  More peers may be added with
	// Peer's Connect method.
	InitialPeers []*net.TCPAddr

	// OnMessage sets the OnMessage field in the generated Peer
	OnMessage func(p *Peer, src PeerName, message []byte) error

	// OnBroadcast sets the OnBroadcast field in the generated Peer
	OnBroadcast func(p *Peer, src PeerName, message []byte) error
}

Config contains parameters needed to connect to the mesh network.

type Logger

type Logger interface {
	Printf(format string, args ...interface{})
}

Logger is a simple logging interface. It can be satisfied by *log.Logger.

type Peer

type Peer struct {
	// OnMessage is called when a unicast (peer-to-peer) message is
	// received, if it is not nil.  A pointer to this struct is passed in.
	OnMessage func(p *Peer, src PeerName, message []byte) error

	// OnBroadcast is called when a broadcast (peer-to-everybody) message
	// is received, if it is not nil.  A pointer to this struct is passed
	// in.
	OnBroadcast func(p *Peer, src PeerName, message []byte) error

	// The following provide access to the underlying mesh structures.
	// Please see https://godoc.org/github.com/weaveworks/mesh for more
	// information.
	TX     mesh.Gossip
	RX     mesh.Gossiper
	Router *mesh.Router
}

Peer represents the local peer in the mesh network.

func New

func New(config Config, l Logger) (*Peer, []error, error)

New creates a new peer joined to the mesh network. The returned slice of errors will only contain errors from the initial connections. If there are fewer errors than initial peers, then at least one connection succeeded. Even if all of the initial connections failed, the returned *Peer's Connect method may be used to attempt more connections.

The returned error is non-nil if the returned peer is unusable.

Unfortunately, due to the underlying library, there's no good way to know if listening for connections succeeded.

func (*Peer) Broadcast

func (p *Peer) Broadcast(message []byte)

Broadcast sends a message to every peer in the mesh network.

func (*Peer) Connect

func (p *Peer) Connect(addrs []*net.TCPAddr) []error

Connect makes connections to the given addresses. Please see New for the meaning of the returned error slice.

func (*Peer) NickNameFromPeerName

func (p *Peer) NickNameFromPeerName(name PeerName) (nickname string, ok bool)

NickNameFromPeerName returns the NickName of the peer in the peer mesh with the given PeerName. It is an O(n) operation over the set of known peers. If the name is not found, ok will be false.

func (*Peer) PeerNameFromNickName

func (p *Peer) PeerNameFromNickName(nickname string) (name PeerName, ok bool)

PeerNameFromNickName returns the PeerName of a peer in the mesh network from with the given NickName. It is an O(n) operation over the set of known peers. If the NickName is not found, ok will be false.

func (*Peer) Send

func (p *Peer) Send(dst PeerName, message []byte) error

Send sends the message to the specified peer.

type PeerName

type PeerName uint64

PeerName uniquely identifies a peer in the mesh network. It is common to use the peer's network adapter's MAC address. Only the lower six bytes are used.

func PeerNameFromHardwareAddr

func PeerNameFromHardwareAddr(h net.HardwareAddr) (PeerName, error)

PeerNameFromHardwareAddr return a PeerName made from the given hardware address.

func PeerNameFromMACAddr

func PeerNameFromMACAddr(a string) (PeerName, error)

PeerNameFromMACAddr transforms a MAC address (or any other colon-separated series of hex-encoded bytes) into a PeerName. Contiguous 0x00's may be elided, as in IPv6 addresses. At most 6 colon-separated hex-encoded bytes may be turned into a PeerName. This is a wrapper around mesh.PeerNameFromString.

func PeerNameFromStringHash

func PeerNameFromStringHash(s string) PeerName

PeerNameFromStringHash transforms s into a PeerName using the first 8 bytes of the SHA512 hash of the string.

func RandomPeerName

func RandomPeerName() (PeerName, error)

RandomPeerName generates a random PeerName.

func UnStringPeerName

func UnStringPeerName(s string) (PeerName, error)

UnStringPeerName reverses the output of PeerName's String() method. It accepts a hex-digits-and-colon name.

func (PeerName) String

func (n PeerName) String() string

String encodes the PeerName as a string similar to a MAC address.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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