go2p

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

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

Go to latest
Published: Sep 10, 2019 License: MIT Imports: 20 Imported by: 0

README

go2p

golang p2p framework

By v-braun - viktor-braun.de.

Build Status codecov Go Report Card Documentation PR welcome

Description

GO2P is a P2P framework, designed with flexibility and simplicity in mind. You can use a pre configured stack (encryption, compression, etc.) or built your own based on the existing modules.

GO2P use the middleware pattern as a core pattern for messages. If you have used expressJS, OWIN or other HTTP/Web based frameworks you should be familiar with that.
The basic idea is that an outgoing message is passed through multiple middleware functions. Each of this functions can manipulate the message.
A middleware function could encrypt, compress, log or sign the message.
Outgoing messages will be processed through the middleware functions and incomming messages in the inverted order:

Installation

go get github.com/v-braun/go2p

Usage

You like code? Checkout the chat example

The simplest way to use this framework is to create a new instance of the full configured TCP based network stack:

    localAddr := "localhost:7077"
	net := go2p.NewNetworkConnectionTCP(*localAddr, &map[string]func(peer *go2p.Peer, msg *go2p.Message){
		"msg": func(peer *go2p.Peer, msg *go2p.Message) {
			fmt.Printf("%s > %s\n", peer.RemoteAddress(), msg.PayloadGetString())
		},
    })
    
    net.OnPeer(func(p *go2p.Peer) {
		fmt.Printf("new peer: %s\n", p.RemoteAddress())
    })
    
    err := net.Start()
	if err != nil {
		panic(err)
    }

    defer net.Stop()
    

    // connects to another peer via tcp
    net.ConnectTo("tcp", "localhost:7077")

    // send a message to the 'msg' route 
    net.SendBroadcast(go2p.NewMessageRoutedFromString("msg", "hello go2p"))



Advanced Usage

The function NewNetworkConnectionTCP is a shorthand for the advanced configuration of a network stack.

	op := go2p.NewTCPOperator("tcp", localAddr) // creates a tcp based operator (net.Dialer and net.Listener)
	peerStore := go2p.NewDefaultPeerStore(10) // creates a simple peer store that limits connections to 10

	conn := go2p.NewNetworkConnection(). // creates a new instance of the builder
		WithOperator(op). // adds the operator to the network stack
		WithPeerStore(peerStore). // adds the peer store to the network stack
		WithMiddleware(go2p.Routes(routes)). // adds the routes middleware
		WithMiddleware(go2p.Headers()). // adds the headers middleware
		WithMiddleware(go2p.Crypt()). // adds encryption
		WithMiddleware(go2p.Log()). // adds logging
		Build() // creates the network 

This code creates a new NetworkConnection that use tcp communication, a default PeerStore and some middlewares.
Outgoing messages will now pass the following middlewares:

(app logic) -> Routing -> Headers -> Crypt -> Log -> (network) 

Incomming messages will pass the following middlewares

(app logic) <- Routing <- Headers <- Crypt <- Log <- (network)

Authors

image
v-braun

Contributing

Make sure to read these guides before getting started:

License

go2p is available under the MIT License. See LICENSE for details.

Documentation

Index

Constants

View Source
const DisconnectedError = errorConstant("disconnected")

DisconnectedError represents Error when a peer is disconnected

Variables

View Source
var EmptyRoutesTable = *new(RoutingTable)

EmptyRoutesTable is a table without any routes

View Source
var ErrInvalidNetwork = errors.New("invalid network")

ErrInvalidNetwork represents an invalid network part in the given address

View Source
var ErrPipeStopProcessing = errors.New("pipe stopped")

ErrPipeStopProcessing is returned when the pipe has stopped it execution

Functions

This section is empty.

Types

type Adapter

type Adapter interface {

	// ReadMessage should read from the underline connection
	// and return a Message object until all data was readed
	// The call should block until an entire Message was readed,
	// an error occoured or the underline connection was closed
	ReadMessage() (*Message, error)

	// WriteMessage write the given message to the underline connection
	WriteMessage(m *Message) error

	// Close should close the underline connection
	Close()

	// LocalAddress returns the local address (example: tcp:127.0.0.1:7000)
	LocalAddress() string

	// RemoteAddress returns the remote address (example: tcp:127.0.0.1:7000)
	RemoteAddress() string
}

Adapter represents a wrapper around a network connection

func NewAdapter

func NewAdapter(conn net.Conn) Adapter

NewAdapter creates a new TCP adapter that wraps the given net.Conn instance

type Message

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

Message represents a p2p message

func NewMessage

func NewMessage() *Message

NewMessage creates a new empty Message

func NewMessageFromData

func NewMessageFromData(data []byte) *Message

NewMessageFromData creates a new Message from the given data

func NewMessageFromString

func NewMessageFromString(data string) *Message

NewMessageFromString creates a new Message from the given string

func NewMessageRoutedFromData

func NewMessageRoutedFromData(path string, data []byte) *Message

NewMessageRoutedFromData creates a new routed message to the handler given by path with the provided data

func NewMessageRoutedFromString

func NewMessageRoutedFromString(path string, content string) *Message

NewMessageRoutedFromString creates a new routed message to the handler given by path with the provided string content

func (*Message) Metadata

func (m *Message) Metadata() maps.Map

Metadata returns a map of metadata assigned to this message

func (*Message) PayloadGet

func (m *Message) PayloadGet() []byte

PayloadGet returns the payload data

func (*Message) PayloadGetString

func (m *Message) PayloadGetString() string

PayloadGetString returns the payload of the message as a string

func (*Message) PayloadSet

func (m *Message) PayloadSet(value []byte)

PayloadSet sets the payload with the given value

func (*Message) PayloadSetString

func (m *Message) PayloadSetString(value string)

PayloadSetString sets the given string as payload of the message

func (*Message) ReadFromConn

func (m *Message) ReadFromConn(c net.Conn) error

ReadFromConn read all data from the given conn object into the payload of the message instance

func (*Message) ReadFromReader

func (m *Message) ReadFromReader(reader *bufio.Reader) error

ReadFromReader read all data from the given reader object into the payload of the message instance

func (*Message) WriteIntoConn

func (m *Message) WriteIntoConn(c net.Conn) error

WriteIntoConn writes the message payload into the given conn instance

func (*Message) WriteIntoWriter

func (m *Message) WriteIntoWriter(writer *bufio.Writer) error

WriteIntoWriter writes the message payload into the given writer instance

type Middleware

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

Middleware represents a wrapped middleware function with additional information for internal usage

func NewMiddleware

func NewMiddleware(name string, action MiddlewareFunc) *Middleware

NewMiddleware wraps the provided action into a Middleware instance

func (*Middleware) String

func (m *Middleware) String() string

String returns the string representation of this instance

type MiddlewareFunc

type MiddlewareFunc func(peer *Peer, pipe *Pipe, msg *Message) (MiddlewareResult, error)

MiddlewareFunc represents a middleware implementation function

func Crypt

func Crypt() (string, MiddlewareFunc)

Crypt returns the crypto middleware. This middleware handles encryption in your communication PublicKeys are exchanged on first peer communication

func Headers

func Headers() (string, MiddlewareFunc)

Headers creates the *headers* middleware store the Message.Annotations() within the payload. With this middleware you can provide (http protocol) "header" like behavior into your communication. You can use it to annotate messages with id's or other information

func Log

func Log() (string, MiddlewareFunc)

Log creates a logging middleware for in and outgoing messages

func Routes

func Routes(rt RoutingTable) (string, MiddlewareFunc)

Routes provides an route based middleware You can listen to specific endpoints and send messages to them This is similar to a controller/action pattern in HTTP frameworks

type MiddlewareResult

type MiddlewareResult int

MiddlewareResult represents a result returned by a middleware possible values are *Stop* and *Next*

const (
	// Stop will be returned by a middleware when the pipe execution should be stopped
	Stop MiddlewareResult = iota

	// Next will be returned by a middleware when the pipe execution should be continued
	Next MiddlewareResult = iota
)

type NetworkConnection

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

NetworkConnection is the main entry point to the p2p network

func NewNetworkConnectionTCP

func NewNetworkConnectionTCP(localAddr string, routes RoutingTable) *NetworkConnection

NewNetworkConnectionTCP provides a full configured TCP based network It use the _DefaultMiddleware_ a TCP based operator and the following middleware:

Routes, Headers, Crypt, Log

func (*NetworkConnection) ConnectTo

func (nc *NetworkConnection) ConnectTo(network string, addr string)

ConnectTo will Dial the provided peer by the given network

func (*NetworkConnection) DisconnectFrom

func (nc *NetworkConnection) DisconnectFrom(addr string)

DisconnectFrom will disconnects the given peer

func (*NetworkConnection) OnMessage

func (nc *NetworkConnection) OnMessage(handler func(p *Peer, msg *Message))

OnMessage regsiters the given handler and call it when a new message is received

func (*NetworkConnection) OnPeer

func (nc *NetworkConnection) OnPeer(handler func(p *Peer))

OnPeer registers the provided handler and call it when a new peer connection is created

func (*NetworkConnection) OnPeerDisconnect

func (nc *NetworkConnection) OnPeerDisconnect(handler func(p *Peer))

OnPeerDisconnect regsiters the given handler and call it when an the connection is lost

func (*NetworkConnection) OnPeerError

func (nc *NetworkConnection) OnPeerError(handler func(p *Peer, err error))

OnPeerError regsiters the given handler and call it when an error during the peer communication occurs

func (*NetworkConnection) Send

func (nc *NetworkConnection) Send(msg *Message, addr string)

Send will send the provided message to the given address

func (*NetworkConnection) SendBroadcast

func (nc *NetworkConnection) SendBroadcast(msg *Message)

SendBroadcast will send the given message to all peers

func (*NetworkConnection) Start

func (nc *NetworkConnection) Start() error

Start will start up the p2p network stack

func (*NetworkConnection) Stop

func (nc *NetworkConnection) Stop()

Stop will shutdown the entire p2p network stack

type NetworkConnectionBuilder

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

NetworkConnectionBuilder provides a fluent interface to create a NetworkConnection

func NewNetworkConnection

func NewNetworkConnection() *NetworkConnectionBuilder

NewNetworkConnection creates a new NetworkBuilder instance to setup a new NetworkConnection

func (*NetworkConnectionBuilder) Build

Build finalize the NetworkConnection setup and creates the new instance

func (*NetworkConnectionBuilder) WithMiddleware

WithMiddleware attach a new Middleware to the NetworkConnection setup

func (*NetworkConnectionBuilder) WithOperator

WithOperator attach a new PeerOperator to the NetworkConnection setup

type OperatorTCP

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

OperatorTCP is an implementation of the PeerOperator inteface that handles TCP based connections. It use an net.Listener for incoming connections and and tcp.Dialer for outgoing.

func NewTCPOperator

func NewTCPOperator(network string, localAddr string) *OperatorTCP

NewTCPOperator creates a new TCP based PeerOperator instance

func (*OperatorTCP) Dial

func (o *OperatorTCP) Dial(network string, addr string) error

Dial connects to the address by the given network

func (*OperatorTCP) OnError

func (o *OperatorTCP) OnError(handler func(err error))

OnError registers the given handler and calls it when a peer error occurs

func (*OperatorTCP) OnPeer

func (o *OperatorTCP) OnPeer(handler func(p Adapter))

OnPeer registers the given handler and calls it when a new peer connection is established

func (*OperatorTCP) Start

func (o *OperatorTCP) Start() error

Start will start the net.Listener and waits for incoming connections

func (*OperatorTCP) Stop

func (o *OperatorTCP) Stop()

Stop will close the underlining net.Listener

type Peer

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

Peer represents a connection to a remote peer

func (*Peer) LocalAddress

func (p *Peer) LocalAddress() string

LocalAddress returns the local address of the current peer

func (*Peer) Metadata

func (p *Peer) Metadata() maps.Map

Metadata returns a map of metadata associated to this peer

func (*Peer) RemoteAddress

func (p *Peer) RemoteAddress() string

RemoteAddress returns the remote address of the current peer

type PeerOperator

type PeerOperator interface {

	// Dial connects to the given address by the given network
	Dial(network string, addr string) error

	// OnPeer registers a handler function that should be called
	// when a new peer connection is established
	OnPeer(handler func(p Adapter))

	// Start the background listening jobs for the operator
	Start() error

	// Stop the background listening jobs for the operator
	Stop()
}

PeerOperator connect peers to the current network connection I provides functionalities for dialing (active connection) and listening (passive connections) over a protocol (tcp/udp/etc)

type Pipe

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

Pipe handles the processing of an message

func (*Pipe) Operation

func (p *Pipe) Operation() PipeOperation

Operation returns the current pipe operation (Send or Receive)

func (*Pipe) Receive

func (p *Pipe) Receive() (*Message, error)

Receive will block the current call until a message was read from the peer or an error occurs.

The message goes only through middlewares that are after the current pipe position

func (*Pipe) Send

func (p *Pipe) Send(msg *Message) error

Send will send the provided message during the current pipe execution.

The message goes only through middlewares that are after the current pipe position

type PipeOperation

type PipeOperation int

PipeOperation represents the pipe direction (Send or Receive)

const (
	// Send represents an outgoing message pipe processing
	Send PipeOperation = iota
	// Receive represents an incoming message pipe processing
	Receive PipeOperation = iota
)

func (PipeOperation) String

func (po PipeOperation) String() string

type RoutingTable

type RoutingTable *map[string]func(peer *Peer, msg *Message)

RoutingTable represents handler registered by a path. A message will be checked for the existence of an annotation with the name "__routes_path" and this value will be used to find a route within the routing table

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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