basic working ping relay simulation
This commit is contained in:
@@ -2,13 +2,16 @@ package client
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||
"github.com/Indra-Labs/indra/pkg/key/prv"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/key/signer"
|
||||
"github.com/Indra-Labs/indra/pkg/node"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
"github.com/Indra-Labs/indra/pkg/types"
|
||||
@@ -29,6 +32,8 @@ import (
|
||||
"github.com/cybriq/qu"
|
||||
)
|
||||
|
||||
const DefaultDeadline = 10 * time.Minute
|
||||
|
||||
var (
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
@@ -43,20 +48,23 @@ type Client struct {
|
||||
Circuits
|
||||
Sessions
|
||||
sync.Mutex
|
||||
*signer.KeySet
|
||||
qu.C
|
||||
}
|
||||
|
||||
func New(tpt ifc.Transport, hdrPrv *prv.Key, no *node.Node,
|
||||
nodes node.Nodes) (c *Client, e error) {
|
||||
|
||||
hdrPub := pub.Derive(hdrPrv)
|
||||
var n *node.Node
|
||||
n, _ = node.New(no.AddrPort, hdrPub, nil, hdrPrv, nil, tpt)
|
||||
no.Transport = tpt
|
||||
no.HeaderPriv = hdrPrv
|
||||
no.HeaderPub = pub.Derive(hdrPrv)
|
||||
c = &Client{
|
||||
Node: n,
|
||||
Nodes: nodes,
|
||||
C: qu.T(),
|
||||
Node: no,
|
||||
Nodes: nodes,
|
||||
ReceiveCache: address.NewReceiveCache(),
|
||||
C: qu.T(),
|
||||
}
|
||||
c.ReceiveCache.Add(address.NewReceiver(hdrPrv))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -80,35 +88,47 @@ func (c *Client) runner() (out bool) {
|
||||
// process received message
|
||||
var onion types.Onion
|
||||
var e error
|
||||
cursor := slice.NewCursor()
|
||||
if onion, e = wire.PeelOnion(b, cursor); check(e) {
|
||||
cur := slice.NewCursor()
|
||||
if onion, e = wire.PeelOnion(b, cur); check(e) {
|
||||
break
|
||||
}
|
||||
switch on := onion.(type) {
|
||||
case *cipher.OnionSkin:
|
||||
c.cipher(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.cipher(on, b, cur)
|
||||
case *confirmation.OnionSkin:
|
||||
c.confirmation(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.confirmation(on, b, cur)
|
||||
case *delay.OnionSkin:
|
||||
c.delay(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.delay(on, b, cur)
|
||||
case *exit.OnionSkin:
|
||||
c.exit(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.exit(on, b, cur)
|
||||
case *forward.OnionSkin:
|
||||
c.forward(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.forward(on, b, cur)
|
||||
case *layer.OnionSkin:
|
||||
c.layer(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.layer(on, b, cur)
|
||||
case *noop.OnionSkin:
|
||||
c.noop(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.noop(on, b, cur)
|
||||
case *purchase.OnionSkin:
|
||||
c.purchase(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.purchase(on, b, cur)
|
||||
case *reply.OnionSkin:
|
||||
c.reply(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.reply(on, b, cur)
|
||||
case *response.OnionSkin:
|
||||
c.response(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.response(on, b, cur)
|
||||
case *session.OnionSkin:
|
||||
c.session(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.session(on, b, cur)
|
||||
case *token.OnionSkin:
|
||||
c.token(on, b)
|
||||
log.I.Ln(reflect.TypeOf(on))
|
||||
c.token(on, b, cur)
|
||||
default:
|
||||
log.I.S("unrecognised packet", b)
|
||||
}
|
||||
@@ -116,59 +136,74 @@ func (c *Client) runner() (out bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Client) cipher(on *cipher.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) cipher(on *cipher.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// This either is in a forward only SendKeys message or we are the buyer
|
||||
// and these are our session keys.
|
||||
}
|
||||
|
||||
func (c *Client) confirmation(on *confirmation.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) confirmation(on *confirmation.OnionSkin, b slice.Bytes,
|
||||
cur *slice.Cursor) {
|
||||
// This will be an 8 byte nonce that confirms a message passed, ping and
|
||||
// cipher onions return these, as they are pure forward messages that
|
||||
// send a message one way and the confirmation is the acknowledgement.
|
||||
log.I.S(on)
|
||||
}
|
||||
|
||||
func (c *Client) delay(on *delay.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) delay(on *delay.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// this is a message to hold the message in the buffer until a duration
|
||||
// elapses. The accounting for the remainder of the message adds a
|
||||
// factor to the effective byte consumption in accordance with the time
|
||||
// to be stored.
|
||||
}
|
||||
|
||||
func (c *Client) exit(on *exit.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) exit(on *exit.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// payload is forwarded to a local port and the response is forwarded
|
||||
// back with a reply header.
|
||||
}
|
||||
|
||||
func (c *Client) forward(on *forward.OnionSkin, b slice.Bytes) {
|
||||
// forward the whole buffer received onwards. Usually there will be an
|
||||
// OnionSkin under this which will be unwrapped by the receiver.
|
||||
func (c *Client) forward(on *forward.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// forward the whole buffer received onwards. Usually there will be a
|
||||
// layer.OnionSkin under this which will be unwrapped by the receiver.
|
||||
if on.AddrPort.String() == c.Node.AddrPort.String() {
|
||||
// it is for us, we want to unwrap the next
|
||||
// part.
|
||||
c.Node.Send(b)
|
||||
log.I.Ln("processing new message")
|
||||
c.Node.Send(b[*cur:])
|
||||
} else {
|
||||
// we need to forward this message onion.
|
||||
log.I.Ln("forwarding")
|
||||
c.Send(on.AddrPort, b)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) layer(on *layer.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) layer(on *layer.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// this is probably an encrypted layer for us.
|
||||
log.I.Ln("decrypting onion skin")
|
||||
// log.I.S(on, b[*cur:].ToBytes())
|
||||
rcv := c.ReceiveCache.FindCloaked(on.Cloak)
|
||||
if rcv == nil {
|
||||
log.I.Ln("no matching key found from cloaked key")
|
||||
return
|
||||
}
|
||||
on.Decrypt(rcv.Key, b, cur)
|
||||
log.I.S(b[*cur:].ToBytes())
|
||||
c.Node.Send(b[*cur:])
|
||||
}
|
||||
|
||||
func (c *Client) noop(on *noop.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) noop(on *noop.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// this won't happen normally
|
||||
}
|
||||
|
||||
func (c *Client) purchase(on *purchase.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) purchase(on *purchase.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// Create a new Session.
|
||||
s := &Session{}
|
||||
c.Mutex.Lock()
|
||||
s.Deadline = time.Now().Add(DefaultDeadline)
|
||||
c.Sessions = append(c.Sessions, s)
|
||||
c.Mutex.Unlock()
|
||||
}
|
||||
|
||||
func (c *Client) reply(on *reply.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) reply(on *reply.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// Reply means another OnionSkin is coming and the payload encryption
|
||||
// uses the Payload key.
|
||||
if on.AddrPort.String() == c.Node.AddrPort.String() {
|
||||
@@ -181,11 +216,11 @@ func (c *Client) reply(on *reply.OnionSkin, b slice.Bytes) {
|
||||
|
||||
}
|
||||
|
||||
func (c *Client) response(on *response.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) response(on *response.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// Response is a payload from an exit message.
|
||||
}
|
||||
|
||||
func (c *Client) session(s *session.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) session(s *session.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// Session is returned from a Purchase message in the reply layers.
|
||||
//
|
||||
// Session has a nonce.ID that is given in the last layer of a LN sphinx
|
||||
@@ -194,7 +229,7 @@ func (c *Client) session(s *session.OnionSkin, b slice.Bytes) {
|
||||
// nonce, so long as it has not yet expired.
|
||||
}
|
||||
|
||||
func (c *Client) token(t *token.OnionSkin, b slice.Bytes) {
|
||||
func (c *Client) token(t *token.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
||||
// not really sure if we are using these.
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,10 +2,83 @@ package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
"github.com/Indra-Labs/indra/pkg/key/prv"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/key/signer"
|
||||
"github.com/Indra-Labs/indra/pkg/node"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
"github.com/Indra-Labs/indra/pkg/transport"
|
||||
"github.com/Indra-Labs/indra/pkg/wire"
|
||||
log2 "github.com/cybriq/proc/pkg/log"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
|
||||
func TestPing(t *testing.T) {
|
||||
log2.CodeLoc = true
|
||||
var clients [4]*Client
|
||||
var nodes [4]*node.Node
|
||||
var transports [4]ifc.Transport
|
||||
var e error
|
||||
for i := range transports {
|
||||
transports[i] = transport.NewSim(4)
|
||||
}
|
||||
for i := range nodes {
|
||||
var hdrPrv, pldPrv *prv.Key
|
||||
if hdrPrv, e = prv.GenerateKey(); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
hdrPub := pub.Derive(hdrPrv)
|
||||
if pldPrv, e = prv.GenerateKey(); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
pldPub := pub.Derive(pldPrv)
|
||||
addr := slice.GenerateRandomAddrPortIPv4()
|
||||
log.I.S(addr)
|
||||
nodes[i], _ = node.New(addr, hdrPub, pldPub, hdrPrv, pldPrv, transports[i])
|
||||
if clients[i], e = New(transports[i], hdrPrv, nodes[i], nil); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
clients[i].AddrPort = nodes[i].AddrPort
|
||||
}
|
||||
// add each node to each other's Nodes except itself.
|
||||
for i := range nodes {
|
||||
for j := range nodes {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
clients[i].Nodes = append(clients[i].Nodes, nodes[j])
|
||||
}
|
||||
}
|
||||
// Start up the clients.
|
||||
for _, v := range clients {
|
||||
go v.Start()
|
||||
}
|
||||
pn := nonce.NewID()
|
||||
var ks *signer.KeySet
|
||||
if _, ks, e = signer.New(); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
var hop [3]*node.Node
|
||||
for i := range clients[0].Nodes {
|
||||
hop[i] = clients[0].Nodes[i]
|
||||
}
|
||||
os := wire.Ping(pn, clients[0].Node, hop, ks)
|
||||
log.I.S(os)
|
||||
o := os.Assemble()
|
||||
b := wire.EncodeOnion(o)
|
||||
// log.I.S(b.ToBytes())
|
||||
hop[0].Send(b)
|
||||
time.Sleep(time.Second * 5)
|
||||
for _, v := range clients {
|
||||
v.Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -52,7 +52,7 @@ func (s Sessions) Find(t nonce.ID) (se *Session) {
|
||||
// NewSession creates a new Session.
|
||||
//
|
||||
// Purchasing a session the seller returns a token, based on a requested data
|
||||
// allocation,
|
||||
// allocation.
|
||||
func NewSession(id nonce.ID, rem uint64, hdr, pld *address.SendEntry,
|
||||
kr *signer.KeySet) (s *Session) {
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ var (
|
||||
// except when the netip.AddrPort is known via the packet sender address.
|
||||
type Node struct {
|
||||
nonce.ID
|
||||
Addr string
|
||||
*netip.AddrPort
|
||||
Addr string
|
||||
AddrPort *netip.AddrPort
|
||||
HeaderPub, PayloadPub *pub.Key
|
||||
HeaderPriv, PayloadPriv *prv.Key
|
||||
ifc.Transport
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package confirmation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
@@ -34,6 +36,11 @@ type OnionSkin struct {
|
||||
nonce.ID
|
||||
}
|
||||
|
||||
func (x *OnionSkin) String() string {
|
||||
return fmt.Sprintf("\n\tnonce: %x\n",
|
||||
x.ID)
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Inner() types.Onion { return nil }
|
||||
func (x *OnionSkin) Insert(o types.Onion) {}
|
||||
func (x *OnionSkin) Len() int { return MinLen }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forward
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
@@ -26,6 +27,11 @@ type OnionSkin struct {
|
||||
types.Onion
|
||||
}
|
||||
|
||||
func (x *OnionSkin) String() string {
|
||||
s, _ := x.AddrPort.MarshalBinary()
|
||||
return fmt.Sprintf("\n\taddrport: %x %v\n", s, x.AddrPort.String())
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Inner() types.Onion { return x.Onion }
|
||||
func (x *OnionSkin) Insert(o types.Onion) { x.Onion = o }
|
||||
func (x *OnionSkin) Len() int {
|
||||
|
||||
@@ -2,6 +2,7 @@ package layer
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"fmt"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/ciph"
|
||||
@@ -42,8 +43,13 @@ type OnionSkin struct {
|
||||
types.Onion
|
||||
}
|
||||
|
||||
func (x *OnionSkin) String() string {
|
||||
return fmt.Sprintf("\n\tnonce: %x\n\tto: %x,\n\tfrom: %x,\n",
|
||||
x.To.GetCloak(), pub.Derive(x.From).ToBytes(), x.Nonce)
|
||||
}
|
||||
|
||||
const MinLen = magicbytes.Len + nonce.IVLen +
|
||||
address.Len + pub.KeyLen + slice.Uint32Len
|
||||
address.Len + pub.KeyLen
|
||||
|
||||
func (x *OnionSkin) Inner() types.Onion { return x.Onion }
|
||||
func (x *OnionSkin) Insert(o types.Onion) { x.Onion = o }
|
||||
|
||||
@@ -72,6 +72,7 @@ func (o OnionSkins) OnionSkin(to *address.Sender, from *prv.Key) OnionSkins {
|
||||
return append(o, &layer.OnionSkin{
|
||||
To: to,
|
||||
From: from,
|
||||
Nonce: nonce.New(),
|
||||
Onion: os,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ var (
|
||||
// GitRef is the gitref, as in refs/heads/branchname.
|
||||
GitRef = "refs/heads/main"
|
||||
// ParentGitCommit is the commit hash of the parent HEAD.
|
||||
ParentGitCommit = "894afbd3a2ec5742387f3203e4e08b906557c319"
|
||||
ParentGitCommit = "d77ece43a28634a1c8502bac025840d70f3b23e2"
|
||||
// BuildTime stores the time when the current binary was built.
|
||||
BuildTime = "2022-12-28T13:19:51Z"
|
||||
BuildTime = "2022-12-28T16:34:23Z"
|
||||
// SemVer lists the (latest) git tag on the build.
|
||||
SemVer = "v0.0.254"
|
||||
SemVer = "v0.0.255"
|
||||
// PathBase is the path base returned from runtime caller.
|
||||
PathBase = "/home/loki/src/github.com/Indra-Labs/indra/"
|
||||
// Major is the major number from the tag.
|
||||
@@ -22,7 +22,7 @@ var (
|
||||
// Minor is the minor number from the tag.
|
||||
Minor = 0
|
||||
// Patch is the patch version number from the tag.
|
||||
Patch = 254
|
||||
Patch = 255
|
||||
)
|
||||
|
||||
// Version returns a pretty printed version information string.
|
||||
|
||||
Reference in New Issue
Block a user