143 lines
3.5 KiB
Go
143 lines
3.5 KiB
Go
// Package node maintains information about peers on the network and associated
|
|
// connection sessions.
|
|
package node
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
"time"
|
|
|
|
"github.com/indra-labs/indra"
|
|
"github.com/indra-labs/indra/pkg/crypto/key/prv"
|
|
"github.com/indra-labs/indra/pkg/crypto/key/pub"
|
|
"github.com/indra-labs/indra/pkg/crypto/nonce"
|
|
"github.com/indra-labs/indra/pkg/identity"
|
|
log2 "github.com/indra-labs/indra/pkg/proc/log"
|
|
"github.com/indra-labs/indra/pkg/service"
|
|
"github.com/indra-labs/indra/pkg/traffic"
|
|
"github.com/indra-labs/indra/pkg/types"
|
|
"github.com/indra-labs/indra/pkg/util/slice"
|
|
)
|
|
|
|
var (
|
|
log = log2.GetLogger(indra.PathBase)
|
|
check = log.E.Chk
|
|
)
|
|
|
|
// Node is a representation of a messaging counterparty. The netip.AddrPort can
|
|
// be nil for the case of a client node that is not in a direct open connection,
|
|
// or for the special node in a client. For this reason all nodes are assigned
|
|
// an ID and will normally be handled by this except when the netip.AddrPort is
|
|
// known via the packet sender address.
|
|
type Node struct {
|
|
nonce.ID
|
|
*identity.Peer
|
|
PingCount int
|
|
LastSeen time.Time
|
|
*traffic.Payments
|
|
service.Services
|
|
}
|
|
|
|
// New creates a new Node. netip.AddrPort is optional if the counterparty is not
|
|
// in direct connection. Also, the idPrv node private key can be nil, as only
|
|
// the node embedded in a client and not the peer node list has one available.
|
|
func New(addr *netip.AddrPort, idPub *pub.Key, idPrv *prv.Key,
|
|
tpt types.Transport) (n *Node, id nonce.ID) {
|
|
|
|
id = nonce.NewID()
|
|
n = &Node{
|
|
ID: id,
|
|
Peer: &identity.Peer{
|
|
AddrPort: addr,
|
|
IdentityPub: idPub,
|
|
IdentityBytes: idPub.ToBytes(),
|
|
IdentityPrv: idPrv,
|
|
Transport: tpt,
|
|
},
|
|
Payments: traffic.NewPayments(),
|
|
}
|
|
return
|
|
}
|
|
|
|
// SendTo delivers a message to a service identified by its port.
|
|
func (n *Node) SendTo(port uint16, b slice.Bytes) (e error) {
|
|
e = fmt.Errorf("port not registered %d", port)
|
|
for i := range n.Services {
|
|
if n.Services[i].Port == port {
|
|
n.Services[i].Send(b)
|
|
e = nil
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// ReceiveFrom returns the channel that receives messages for a given port.
|
|
func (n *Node) ReceiveFrom(port uint16) (b <-chan slice.Bytes) {
|
|
for i := range n.Services {
|
|
if n.Services[i].Port == port {
|
|
log.T.Ln("receivefrom")
|
|
b = n.Services[i].Receive()
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
type Nodes []*Node
|
|
|
|
// NewNodes creates an empty Nodes
|
|
func NewNodes() (n Nodes) { return Nodes{} }
|
|
|
|
// Len returns the length of a Nodes.
|
|
func (n Nodes) Len() int { return len(n) }
|
|
|
|
// Add a Node to a Nodes.
|
|
func (n Nodes) Add(nn *Node) Nodes { return append(n, nn) }
|
|
|
|
// FindByID searches for a Node by ID.
|
|
func (n Nodes) FindByID(i nonce.ID) (no *Node) {
|
|
for _, nn := range n {
|
|
if nn.ID == i {
|
|
no = nn
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// FindByAddrPort searches for a Node by netip.AddrPort.
|
|
func (n Nodes) FindByAddrPort(id *netip.AddrPort) (no *Node) {
|
|
for _, nn := range n {
|
|
if nn.AddrPort.String() == id.String() {
|
|
no = nn
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// DeleteByID deletes a node identified by an ID.
|
|
func (n Nodes) DeleteByID(ii nonce.ID) (nn Nodes, e error) {
|
|
e, nn = fmt.Errorf("id %x not found", ii), n
|
|
for i := range n {
|
|
if n[i].ID == ii {
|
|
return append(n[:i], n[i+1:]...), nil
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// DeleteByAddrPort deletes a node identified by a netip.AddrPort.
|
|
func (n Nodes) DeleteByAddrPort(ip *netip.AddrPort) (nn Nodes, e error) {
|
|
e, nn = fmt.Errorf("node with ip %v not found", ip), n
|
|
for i := range n {
|
|
if n[i].AddrPort.String() == ip.String() {
|
|
nn = append(n[:i], n[i+1:]...)
|
|
e = nil
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|