Files
indra/pkg/relay/helper-sendonion.go
2023-02-25 19:09:28 +00:00

105 lines
2.5 KiB
Go

package relay
import (
"net/netip"
"time"
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
"git-indra.lan/indra-labs/indra/pkg/messages/balance"
"git-indra.lan/indra-labs/indra/pkg/messages/confirm"
"git-indra.lan/indra-labs/indra/pkg/messages/crypt"
"git-indra.lan/indra-labs/indra/pkg/messages/exit"
"git-indra.lan/indra-labs/indra/pkg/messages/forward"
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
"git-indra.lan/indra-labs/indra/pkg/util/slice"
)
func (eng *Engine) SendOnion(ap *netip.AddrPort, o Skins,
responseHook func(id nonce.ID, b slice.Bytes), timeout time.Duration) {
if timeout == 0 {
timeout = DefaultTimeout
}
b := Encode(o.Assemble())
var billable []nonce.ID
var ret nonce.ID
var last nonce.ID
var port uint16
var postAcct []func()
var sessions Sessions
// do client accounting
skip := false
for i := range o {
if skip {
skip = false
continue
}
switch on := o[i].(type) {
case *crypt.Layer:
s := eng.FindSessionByHeaderPub(on.ToHeaderPub)
if s == nil {
continue
}
sessions = append(sessions, s)
// The last hop needs no accounting as it's us!
if i == len(o)-1 {
// The session used for the last hop is stored, however.
ret = s.ID
billable = append(billable, s.ID)
break
}
switch on2 := o[i+1].(type) {
case *forward.Layer:
billable = append(billable, s.ID)
postAcct = append(postAcct,
func() {
eng.DecSession(s.ID,
s.RelayRate*
lnwire.MilliSatoshi(len(b))/1024/1024, true,
"forward")
})
case *reverse.Layer:
billable = append(billable, s.ID)
case *exit.Layer:
for j := range s.Services {
if s.Services[j].Port != on2.Port {
continue
}
port = on2.Port
postAcct = append(postAcct,
func() {
eng.DecSession(s.ID,
s.Services[j].RelayRate*
lnwire.MilliSatoshi(len(b)/2)/1024/1024,
true, "exit")
})
break
}
billable = append(billable, s.ID)
last = on2.ID
skip = true
case *getbalance.Layer:
last = s.ID
billable = append(billable, s.ID)
skip = true
}
case *confirm.Layer:
last = on.ID
case *balance.Layer:
last = on.ID
}
}
if responseHook == nil {
responseHook = func(_ nonce.ID, _ slice.Bytes) {
log.D.Ln("nil response hook")
}
}
eng.PendingResponses.Add(last, len(b), sessions, billable, ret, port,
responseHook, postAcct)
log.T.Ln("sending out onion")
eng.Send(ap, b)
}