neonet

package
v1.8.2-0...-f7776fc Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2024 License: GPL-2.0, GPL-3.0 Imports: 29 Imported by: 0

Documentation

Overview

Package neonet provides service to establish links and exchange messages in a NEO network.

A NEO node - node link can be established with DialLink and ListenLink similarly to how it is done in standard package net. Once established, a link (NodeLink) provides service for multiplexing several communication connections on top of it. Connections (Conn) in turn provide service to exchange NEO protocol messages.

New connections can be created with link.NewConn(). Once connection is created and a message is sent over it, on peer's side another corresponding new connection can be accepted via link.Accept(), and all further communication send/receive exchange will be happening in between those 2 connections.

Use conn.Send and conn.Recv to actually exchange messages. See Conn documentation for other message-exchange utilities like Ask and Expect.

See also package lab.nexedi.com/kirr/neo/go/neo/proto for definition of NEO messages.

Lightweight mode

In situations when created connections are used to only send/receive 1 request/response, the overhead to create/shutdown full connections could be too much. Unfortunately this is exactly the mode that is currently primarily used for compatibility with NEO/py. To help mitigate the overhead in such scenarios, lightweight connections mode is provided:

At requester side, one message can be sent over node link with link.Send1 . Inside a connection will be created and then shut down, but since the code manages whole process internally and does not show the connection to user, it can optimize those operations significantly. Similarly link.Ask1 sends 1 request, receives 1 response, and then puts the connection back into pool for later reuse.

At receiver side, link.Recv1 accepts a connection with the first message remote peer sent us when establishing it, and wraps the result into Request object. The Request contains the message received and internally the connection. A response can be sent back via Request.Reply. Then once Request.Close is called the connection object that was accepted is immediately put back into pool for later reuse.

Joining network

Besides plain TCP, NEO clusters are frequently configured to use TLS in peer-to-peer mode and/or network virtualisation. A networker suitable for interoperating with nodes in such a cluster can be created via Join. See Join and Config for details.

Index

Constants

This section is empty.

Variables

View Source
var ErrClosedConn = errors.New("connection is closed")
View Source
var ErrLinkClosed = errors.New("node link is closed") // operations on closed NodeLink
View Source
var ErrLinkDown = errors.New("node link is down") // e.g. due to IO error
View Source
var ErrLinkManyConn = errors.New("too many opened connections")
View Source
var ErrLinkNoListen = errors.New("node link is not listening for incoming connections")
View Source
var ErrPktTooBig = errors.New("packet too big")

Functions

func Join

func Join(ctx context.Context, cfg Config) (net xnet.Networker, err error)

Join returns network access-point suitable for interoperating with nodes in a NEO cluster according to config.

Types

type Config

type Config struct {
	// CA/Cert/Key, if non-empty, tells to use TLS in peer-to-peer mode
	// with CA certificate and public/private node keys taken from specified files.
	CA, Cert, Key string

	// LoNode, if non-empty, tells to use lonet as underlying network.
	// Network and hostname should be specified as "<net>/<host>".
	LoNode string
}

Config specifies network configuration for Join.

Empty config means to use plain TCP networking for inter-node exchange.

type Conn

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

Conn is a connection established over NodeLink.

Messages can be sent and received over it. Once connection is no longer needed it has to be closed.

It is safe to use Conn from multiple goroutines simultaneously.

func (*Conn) Ask

func (c *Conn) Ask(req proto.Msg, resp proto.Msg) error

Ask sends request and receives a response.

It expects response to be either of resp type or proto.Error:

If resp-type message is received, it is decoded inplace and nil is returned. If proto.Error message is received, it is returned as error.

Otherwise returned error describes the problem.

XXX return proto.Error explicitly?

func (*Conn) Close

func (c *Conn) Close() error

Close closes connection.

Any blocked Send*() or Recv*() will be unblocked and return error.

NOTE for Send() - once transmission was started - it will complete in the background on the wire not to break node-node link framing.

It is safe to call Close several times.

func (*Conn) CloseRecv

func (c *Conn) CloseRecv()

CloseRecv closes reading end of connection.

Any blocked Recv*() will be unblocked and return error. The peer will receive "connection closed" if it tries to send anything after and for messages already in local rx queue.

It is safe to call CloseRecv several times.

func (*Conn) ConnID

func (c *Conn) ConnID() uint32

ConnID returns connection identifier used for the connection.

func (*Conn) Expect

func (c *Conn) Expect(msgv ...proto.Msg) (which int, err error)

Expect receives message and checks it is one of expected types.

If verification is successful the message is decoded inplace and returned which indicates index of received message.

On error (-1, err) is returned.

func (c *Conn) Link() *NodeLink

Link returns underlying NodeLink of this connection.

func (*Conn) Recv

func (c *Conn) Recv() (proto.Msg, error)

Recv receives message from the connection.

func (*Conn) Send

func (c *Conn) Send(msg proto.Msg) error

Send sends message over the connection.

func (*Conn) String

func (c *Conn) String() string

type ConnError

type ConnError struct {
	Link   *NodeLink
	ConnId uint32 // NOTE Conn's are reused - cannot use *Conn here
	Op     string
	Err    error
}

ConnError is returned by Conn operations.

func (*ConnError) Cause

func (e *ConnError) Cause() error

func (*ConnError) Error

func (e *ConnError) Error() string

func (*ConnError) Unwrap

func (e *ConnError) Unwrap() error

type LinkError

type LinkError struct {
	Link *NodeLink
	Op   string
	Err  error
}

LinkError is returned by NodeLink operations.

func (*LinkError) Cause

func (e *LinkError) Cause() error

func (*LinkError) Error

func (e *LinkError) Error() string

func (*LinkError) Unwrap

func (e *LinkError) Unwrap() error

type LinkListener

type LinkListener interface {
	// from xnet.Listener:
	Close() error
	Addr() net.Addr

	// Accept returns new incoming connection wrapped into NodeLink.
	// It accepts only those connections which pass NEO protocol handshake.
	Accept(ctx context.Context) (*NodeLink, error)
}

LinkListener is xnet.Listener adapted to return handshaked NodeLink on Accept.

func ListenLink(ctx context.Context, net xnet.Networker, laddr string) (LinkListener, error)

ListenLink starts listening on laddr for incoming connections and wraps them as NodeLink.

The listener accepts only those connections that pass NEO protocol handshake.

func NewLinkListener

func NewLinkListener(inner xnet.Listener) LinkListener

NewLinkListener creates LinkListener which accepts connections from an inner net.Listener and wraps them as NodeLink.

The listener accepts only those connections that pass NEO protocol handshake.

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

NodeLink is a node-node link in NEO.

A node-node link represents bidirectional symmetrical communication channel in between 2 NEO nodes. The link provides service for multiplexing several communication connections on top of the node-node link.

New connection can be created with .NewConn() . Once connection is created and data is sent over it, on peer's side another corresponding new connection can be accepted via .Accept(), and all further communication send/receive exchange will be happening in between those 2 connections.

A NodeLink has to be explicitly closed, once it is no longer needed.

It is safe to use NodeLink from multiple goroutines simultaneously.

func DialLink(ctx context.Context, net xnet.Networker, addr string) (link *NodeLink, err error)

DialLink connects to address on given network, performs NEO protocol handshake and wraps the connection as NodeLink.

func (*NodeLink) Accept

func (link *NodeLink) Accept() (*Conn, error)

Accept waits for and accepts incoming connection on top of node-node link.

func (*NodeLink) Ask1

func (link *NodeLink) Ask1(req proto.Msg, resp proto.Msg) (err error)

Ask1 sends request and receives response in 1-1 model.

See Conn.Ask for semantic details.

See "Lightweight mode" in top-level package doc for overview.

func (*NodeLink) Close

func (link *NodeLink) Close() error

Close closes node-node link.

All blocking operations - Accept and IO on associated connections established over node link - are automatically interrupted with an error. Underlying raw connection is closed. It is safe to call Close several times.

func (*NodeLink) CloseAccept

func (link *NodeLink) CloseAccept()

CloseAccept instructs node link to not accept incoming connections anymore.

Any blocked Accept() will be unblocked and return error. The peer will receive "connection refused" if it tries to connect after and for already-queued connection requests.

It is safe to call CloseAccept several times.

func (*NodeLink) LocalAddr

func (link *NodeLink) LocalAddr() net.Addr

LocalAddr returns local address of the underlying link to peer.

func (*NodeLink) NewConn

func (link *NodeLink) NewConn() (*Conn, error)

NewConn creates new connection on top of node-node link.

func (*NodeLink) Recv1

func (link *NodeLink) Recv1() (Request, error)

Recv1 accepts a connection with the first message peer sent us when establishing it.

See "Lightweight mode" in top-level package doc for overview.

func (*NodeLink) RemoteAddr

func (link *NodeLink) RemoteAddr() net.Addr

RemoteAddr returns remote address of the underlying link to peer.

func (*NodeLink) Send1

func (link *NodeLink) Send1(msg proto.Msg) error

Send1 sends one message over new connection.

It creates new connection itself internally, and shuts down it after transmission completes.

See "Lightweight mode" in top-level package doc for overview.

func (*NodeLink) String

func (link *NodeLink) String() string

type Request

type Request struct {
	Msg proto.Msg
	// contains filtered or unexported fields
}

Request is a message received from the link + (internally) connection handle to make a reply.

Request represents 1 request - 0|1 reply interaction model.

See "Lightweight mode" in top-level package doc for overview.

func (*Request) Close

func (req *Request) Close()

Close must be called to free request resources.

Close must be called exactly once. The request object cannot be used any more after call to Close.

See "Lightweight mode" in top-level package doc for overview.

func (req *Request) Link() *NodeLink

func (*Request) Reply

func (req *Request) Reply(resp proto.Msg) error

Reply sends response to request.

See "Lightweight mode" in top-level package doc for overview.

Jump to

Keyboard shortcuts

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