sym-encryption #1
@ -2,11 +2,8 @@
|
||||
|
||||
## Roadmap
|
||||
|
||||
* Use probe and relayed-probe packets vs ping/pong.
|
||||
* Rename Mediator -> Relay
|
||||
* Node: use symmetric encryption after handshake
|
||||
* AEAD-AES uses a 12 byte nonce. We need to shrink the header:
|
||||
* Remove Forward and replace it with a HeaderFlags bitfield.
|
||||
* Forward, Asym/Sym, ...
|
||||
* Use default port 456
|
||||
* Remove signing key from hub
|
||||
* Peer: UDP hole-punching
|
||||
|
@ -112,7 +112,7 @@ func main(netName, listenIP string, port uint16) {
|
||||
}
|
||||
|
||||
go newHubPoller(netName, conf, peers).Run()
|
||||
go readFromConn(conf.PeerIP, conn, peers)
|
||||
go readFromConn(conn, peers)
|
||||
readFromIFace(iface, peers)
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ func determinePort(confPort, portFromCommandLine uint16) uint16 {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func readFromConn(localIP byte, conn *net.UDPConn, peers remotePeers) {
|
||||
func readFromConn(conn *net.UDPConn, peers remotePeers) {
|
||||
|
||||
defer panicHandler()
|
||||
|
||||
|
165
node/packets-util.go
Normal file
165
node/packets-util.go
Normal file
@ -0,0 +1,165 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
"vppn/fasttime"
|
||||
)
|
||||
|
||||
var (
|
||||
traceIDCounter uint64
|
||||
)
|
||||
|
||||
func newTraceID() uint64 {
|
||||
return uint64(fasttime.Now()<<30) + atomic.AddUint64(&traceIDCounter, 1)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type binWriter struct {
|
||||
b []byte
|
||||
i int
|
||||
}
|
||||
|
||||
func newBinWriter(buf []byte) *binWriter {
|
||||
buf = buf[:cap(buf)]
|
||||
return &binWriter{buf, 0}
|
||||
}
|
||||
|
||||
func (w *binWriter) Bool(b bool) *binWriter {
|
||||
if b {
|
||||
return w.Byte(1)
|
||||
}
|
||||
return w.Byte(0)
|
||||
}
|
||||
|
||||
func (w *binWriter) Byte(b byte) *binWriter {
|
||||
w.b[w.i] = b
|
||||
w.i++
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *binWriter) SharedKey(key [32]byte) *binWriter {
|
||||
copy(w.b[w.i:w.i+32], key[:])
|
||||
w.i += 32
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *binWriter) Uint16(x uint16) *binWriter {
|
||||
*(*uint16)(unsafe.Pointer(&w.b[w.i])) = x
|
||||
w.i += 2
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *binWriter) Uint64(x uint64) *binWriter {
|
||||
*(*uint64)(unsafe.Pointer(&w.b[w.i])) = x
|
||||
w.i += 8
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *binWriter) Int64(x int64) *binWriter {
|
||||
*(*int64)(unsafe.Pointer(&w.b[w.i])) = x
|
||||
w.i += 8
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *binWriter) AddrPort(addrPort netip.AddrPort) *binWriter {
|
||||
addr := addrPort.Addr().As16()
|
||||
copy(w.b[w.i:w.i+16], addr[:])
|
||||
w.i += 16
|
||||
return w.Uint16(addrPort.Port())
|
||||
}
|
||||
|
||||
func (w *binWriter) Build() []byte {
|
||||
return w.b[:w.i]
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type binReader struct {
|
||||
b []byte
|
||||
i int
|
||||
err error
|
||||
}
|
||||
|
||||
func newBinReader(buf []byte) *binReader {
|
||||
return &binReader{b: buf}
|
||||
}
|
||||
|
||||
func (r *binReader) hasBytes(n int) bool {
|
||||
if r.err != nil || (len(r.b)-r.i) < n {
|
||||
r.err = errMalformedPacket
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *binReader) Bool(b *bool) *binReader {
|
||||
var bb byte
|
||||
r.Byte(&bb)
|
||||
*b = bb != 0
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) Byte(b *byte) *binReader {
|
||||
if !r.hasBytes(1) {
|
||||
return r
|
||||
}
|
||||
*b = r.b[r.i]
|
||||
r.i++
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) SharedKey(x *[32]byte) *binReader {
|
||||
if !r.hasBytes(32) {
|
||||
return r
|
||||
}
|
||||
*x = ([32]byte)(r.b[r.i : r.i+32])
|
||||
r.i += 32
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) Uint16(x *uint16) *binReader {
|
||||
if !r.hasBytes(2) {
|
||||
return r
|
||||
}
|
||||
*x = *(*uint16)(unsafe.Pointer(&r.b[r.i]))
|
||||
r.i += 2
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) Uint64(x *uint64) *binReader {
|
||||
if !r.hasBytes(8) {
|
||||
return r
|
||||
}
|
||||
*x = *(*uint64)(unsafe.Pointer(&r.b[r.i]))
|
||||
r.i += 8
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) Int64(x *int64) *binReader {
|
||||
if !r.hasBytes(8) {
|
||||
return r
|
||||
}
|
||||
*x = *(*int64)(unsafe.Pointer(&r.b[r.i]))
|
||||
r.i += 8
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) AddrPort(x *netip.AddrPort) *binReader {
|
||||
if !r.hasBytes(18) {
|
||||
return r
|
||||
}
|
||||
addr := netip.AddrFrom16(([16]byte)(r.b[r.i : r.i+16]))
|
||||
addr = addr.Unmap()
|
||||
r.i += 16
|
||||
var port uint16
|
||||
r.Uint16(&port)
|
||||
*x = netip.AddrPortFrom(addr, port)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *binReader) Error() error {
|
||||
return r.err
|
||||
}
|
40
node/packets-util_test.go
Normal file
40
node/packets-util_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBinWriteRead(t *testing.T) {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
type Item struct {
|
||||
Type byte
|
||||
TraceID uint64
|
||||
DestAddr netip.AddrPort
|
||||
}
|
||||
|
||||
in := Item{1, 2, netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 22)}
|
||||
|
||||
buf = newBinWriter(buf).
|
||||
Byte(in.Type).
|
||||
Uint64(in.TraceID).
|
||||
AddrPort(in.DestAddr).
|
||||
Build()
|
||||
|
||||
out := Item{}
|
||||
|
||||
err := newBinReader(buf).
|
||||
Byte(&out.Type).
|
||||
Uint64(&out.TraceID).
|
||||
AddrPort(&out.DestAddr).
|
||||
Error()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(in, out) {
|
||||
t.Fatal(in, out)
|
||||
}
|
||||
}
|
100
node/packets.go
100
node/packets.go
@ -13,8 +13,12 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
packetTypePing = iota + 1
|
||||
packetTypeSyn = iota + 1
|
||||
packetTypeSynAck
|
||||
packetTypeAck
|
||||
packetTypePing
|
||||
packetTypePong
|
||||
packetTypeRelayed
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -31,6 +35,8 @@ func (p *controlPacket) ParsePayload(buf []byte) (err error) {
|
||||
p.Payload, err = parsePingPacket(buf)
|
||||
case packetTypePong:
|
||||
p.Payload, err = parsePongPacket(buf)
|
||||
case packetTypeSyn:
|
||||
p.Payload, err = parseSynPacket(buf)
|
||||
default:
|
||||
return errUnknownPacketType
|
||||
}
|
||||
@ -39,34 +45,102 @@ func (p *controlPacket) ParsePayload(buf []byte) (err error) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type synPacket struct {
|
||||
TraceID uint64 // TraceID to match response w/ request.
|
||||
SharedKey [32]byte // Our shared key.
|
||||
ServerAddr netip.AddrPort // The address we're sending to.
|
||||
Direct bool // True if this is request isn't relayed.
|
||||
}
|
||||
|
||||
func (p synPacket) Marshal(buf []byte) []byte {
|
||||
return newBinWriter(buf).
|
||||
Byte(packetTypeSyn).
|
||||
Uint64(p.TraceID).
|
||||
SharedKey(p.SharedKey).
|
||||
AddrPort(p.ServerAddr).
|
||||
Bool(p.Direct).
|
||||
Build()
|
||||
}
|
||||
|
||||
func parseSynPacket(buf []byte) (p synPacket, err error) {
|
||||
err = newBinReader(buf[1:]).
|
||||
Uint64(&p.TraceID).
|
||||
SharedKey(&p.SharedKey).
|
||||
AddrPort(&p.ServerAddr).
|
||||
Bool(&p.Direct).
|
||||
Error()
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type synAckPacket struct {
|
||||
TraceID uint64
|
||||
}
|
||||
|
||||
func (p synAckPacket) Marshal(buf []byte) []byte {
|
||||
return newBinWriter(buf).
|
||||
Byte(packetTypeSynAck).
|
||||
Uint64(p.TraceID).
|
||||
Build()
|
||||
}
|
||||
|
||||
func parseSynAckPacket(buf []byte) (p synAckPacket, err error) {
|
||||
err = newBinReader(buf[1:]).
|
||||
Uint64(&p.TraceID).
|
||||
Error()
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type ackPacket struct {
|
||||
TraceID uint64
|
||||
}
|
||||
|
||||
func (p ackPacket) Marshal(buf []byte) []byte {
|
||||
return newBinWriter(buf).
|
||||
Byte(packetTypeSynAck).
|
||||
Uint64(p.TraceID).
|
||||
Build()
|
||||
}
|
||||
|
||||
func parseAckPacket(buf []byte) (p ackPacket, err error) {
|
||||
err = newBinReader(buf[1:]).
|
||||
Uint64(&p.TraceID).
|
||||
Error()
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// A pingPacket is sent from a node acting as a client, to a node acting
|
||||
// as a server. It always contains the shared key the client is expecting
|
||||
// to use for data encryption with the server.
|
||||
type pingPacket struct {
|
||||
SentAt int64 // UnixMilli.
|
||||
SentAt int64 // UnixMilli. // Not used. Use traceID.
|
||||
SharedKey [32]byte
|
||||
}
|
||||
|
||||
func newPingPacket(sharedKey [32]byte) (pp pingPacket) {
|
||||
pp.SentAt = time.Now().UnixMilli()
|
||||
copy(pp.SharedKey[:], sharedKey[:])
|
||||
pp.SharedKey = sharedKey
|
||||
return
|
||||
}
|
||||
|
||||
func (p pingPacket) Marshal(buf []byte) []byte {
|
||||
buf = buf[:41]
|
||||
buf[0] = packetTypePing
|
||||
*(*uint64)(unsafe.Pointer(&buf[1])) = uint64(p.SentAt)
|
||||
copy(buf[9:41], p.SharedKey[:])
|
||||
return buf
|
||||
return newBinWriter(buf).
|
||||
Byte(packetTypePing).
|
||||
Int64(p.SentAt).
|
||||
SharedKey(p.SharedKey).
|
||||
Build()
|
||||
}
|
||||
|
||||
func parsePingPacket(buf []byte) (p pingPacket, err error) {
|
||||
if len(buf) != 41 {
|
||||
return p, errMalformedPacket
|
||||
}
|
||||
p.SentAt = *(*int64)(unsafe.Pointer(&buf[1]))
|
||||
copy(p.SharedKey[:], buf[9:41])
|
||||
err = newBinReader(buf[1:]).
|
||||
Int64(&p.SentAt).
|
||||
SharedKey(&p.SharedKey).
|
||||
Error()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,59 @@ package node
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPacketSyn(t *testing.T) {
|
||||
in := synPacket{
|
||||
TraceID: newTraceID(),
|
||||
Direct: true,
|
||||
ServerAddr: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 34),
|
||||
}
|
||||
rand.Read(in.SharedKey[:])
|
||||
|
||||
out, err := parseSynPacket(in.Marshal(make([]byte, bufferSize)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(in, out) {
|
||||
t.Fatal("\n", in, "\n", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketSynAck(t *testing.T) {
|
||||
in := synAckPacket{
|
||||
TraceID: newTraceID(),
|
||||
}
|
||||
|
||||
out, err := parseSynAckPacket(in.Marshal(make([]byte, bufferSize)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(in, out) {
|
||||
t.Fatal("\n", in, "\n", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketAck(t *testing.T) {
|
||||
in := ackPacket{
|
||||
TraceID: newTraceID(),
|
||||
}
|
||||
|
||||
out, err := parseAckPacket(in.Marshal(make([]byte, bufferSize)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(in, out) {
|
||||
t.Fatal("\n", in, "\n", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketPing(t *testing.T) {
|
||||
sharedKey := make([]byte, 32)
|
||||
rand.Read(sharedKey)
|
||||
|
@ -12,7 +12,14 @@ import (
|
||||
|
||||
type peerState interface {
|
||||
Name() string
|
||||
OnSyn(netip.AddrPort, synPacket) peerState
|
||||
OnSynAck(netip.AddrPort, synAckPacket) peerState
|
||||
OnAck(netip.AddrPort, ackPacket) peerState
|
||||
|
||||
// When the peer is updated, we reset. Handled by base state.
|
||||
OnPeerUpdate(*m.Peer) peerState
|
||||
|
||||
// To determe up / dataCipher. Handled by base state.
|
||||
OnPing(netip.AddrPort, pingPacket) peerState
|
||||
OnPong(netip.AddrPort, pongPacket) peerState
|
||||
OnPingTimer() peerState
|
||||
@ -24,6 +31,7 @@ type peerState interface {
|
||||
type stateBase struct {
|
||||
// The purpose of this state machine is to manage this published data.
|
||||
published *atomic.Pointer[peerRoutingData]
|
||||
staged peerRoutingData // Local copy of shared data. See publish().
|
||||
|
||||
// The other remote peers.
|
||||
peers *remotePeers
|
||||
@ -41,7 +49,6 @@ type stateBase struct {
|
||||
// Mutable peer data.
|
||||
peer *m.Peer
|
||||
remotePub bool
|
||||
routingData peerRoutingData // Local copy of shared data. See publish().
|
||||
|
||||
// Timers
|
||||
pingTimer *time.Timer
|
||||
@ -69,19 +76,19 @@ func (s *stateBase) OnPeerUpdate(peer *m.Peer) peerState {
|
||||
|
||||
func (s *stateBase) selectStateFromPeer(peer *m.Peer) peerState {
|
||||
s.peer = peer
|
||||
s.routingData = peerRoutingData{}
|
||||
s.staged = peerRoutingData{}
|
||||
defer s.publish()
|
||||
|
||||
if peer == nil {
|
||||
return newStateNoPeer(s)
|
||||
}
|
||||
|
||||
s.routingData.controlCipher = newControlCipher(s.privKey, peer.EncPubKey)
|
||||
s.staged.controlCipher = newControlCipher(s.privKey, peer.EncPubKey)
|
||||
|
||||
ip, isValid := netip.AddrFromSlice(peer.PublicIP)
|
||||
if isValid {
|
||||
s.remotePub = true
|
||||
s.routingData.remoteAddr = netip.AddrPortFrom(ip, peer.Port)
|
||||
s.routingData.relay = peer.Mediator
|
||||
s.staged.remoteAddr = netip.AddrPortFrom(ip, peer.Port)
|
||||
s.staged.relay = peer.Mediator
|
||||
|
||||
if s.localPub && s.localIP < s.remoteIP {
|
||||
return newStateServer(s)
|
||||
@ -96,10 +103,16 @@ func (s *stateBase) selectStateFromPeer(peer *m.Peer) peerState {
|
||||
return newStateSelectRelay(s)
|
||||
}
|
||||
|
||||
func (s *stateBase) OnSyn(rAddr netip.AddrPort, p synPacket) peerState { return nil }
|
||||
func (s *stateBase) OnSynAck(rAddr netip.AddrPort, p synAckPacket) peerState { return nil }
|
||||
func (s *stateBase) OnAck(rAddr netip.AddrPort, p ackPacket) peerState { return nil }
|
||||
func (s *stateBase) OnPing(rAddr netip.AddrPort, p pingPacket) peerState { return nil }
|
||||
func (s *stateBase) OnPong(rAddr netip.AddrPort, p pongPacket) peerState { return nil }
|
||||
func (s *stateBase) OnPingTimer() peerState { return nil }
|
||||
func (s *stateBase) OnTimeoutTimer() peerState { return nil }
|
||||
|
||||
func (s *stateBase) OnTimeoutTimer() peerState {
|
||||
return s.selectStateFromPeer(s.peer)
|
||||
}
|
||||
|
||||
// Helpers.
|
||||
|
||||
@ -113,7 +126,7 @@ func (s *stateBase) logf(msg string, args ...any) {
|
||||
}
|
||||
|
||||
func (s *stateBase) publish() {
|
||||
data := s.routingData
|
||||
data := s.staged
|
||||
s.published.Store(&data)
|
||||
}
|
||||
|
||||
@ -148,11 +161,11 @@ func (s *stateBase) sendControlPacket(pkt interface{ Marshal([]byte) []byte }) {
|
||||
DestIP: s.remoteIP,
|
||||
}
|
||||
|
||||
buf = s.routingData.controlCipher.Encrypt(h, buf, s.encBuf)
|
||||
if s.routingData.relayIP != 0 {
|
||||
s.peers[s.routingData.relayIP].RelayFor(s.remoteIP, buf)
|
||||
buf = s.staged.controlCipher.Encrypt(h, buf, s.encBuf)
|
||||
if s.staged.relayIP != 0 {
|
||||
s.peers[s.staged.relayIP].RelayFor(s.remoteIP, buf)
|
||||
} else {
|
||||
s.conn.WriteTo(buf, s.routingData.remoteAddr)
|
||||
s.conn.WriteTo(buf, s.staged.remoteAddr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,6 +175,8 @@ type stateNoPeer struct{ *stateBase }
|
||||
|
||||
func newStateNoPeer(b *stateBase) *stateNoPeer {
|
||||
s := &stateNoPeer{b}
|
||||
s.pingTimer.Stop()
|
||||
s.timeoutTimer.Stop()
|
||||
s.publish()
|
||||
return s
|
||||
}
|
||||
@ -177,8 +192,8 @@ func newStateClient(b *stateBase) peerState {
|
||||
s := &stateClient{stateBase: b}
|
||||
s.publish()
|
||||
|
||||
s.routingData.dataCipher = newDataCipher()
|
||||
s.sharedKey = s.routingData.dataCipher.Key()
|
||||
s.staged.dataCipher = newDataCipher()
|
||||
s.sharedKey = s.staged.dataCipher.Key()
|
||||
|
||||
s.sendPing(s.sharedKey)
|
||||
s.resetPingTimer()
|
||||
@ -189,8 +204,8 @@ func newStateClient(b *stateBase) peerState {
|
||||
func (s *stateClient) Name() string { return "client" }
|
||||
|
||||
func (s *stateClient) OnPong(addr netip.AddrPort, p pongPacket) peerState {
|
||||
if !s.routingData.up {
|
||||
s.routingData.up = true
|
||||
if !s.staged.up {
|
||||
s.staged.up = true
|
||||
s.publish()
|
||||
}
|
||||
s.resetTimeoutTimer()
|
||||
@ -204,7 +219,7 @@ func (s *stateClient) OnPingTimer() peerState {
|
||||
}
|
||||
|
||||
func (s *stateClient) OnTimeoutTimer() peerState {
|
||||
s.routingData.up = false
|
||||
s.staged.up = false
|
||||
s.publish()
|
||||
return nil
|
||||
}
|
||||
@ -226,17 +241,17 @@ func newStateServer(b *stateBase) peerState {
|
||||
func (s *stateServer) Name() string { return "server" }
|
||||
|
||||
func (s *stateServer) OnPing(addr netip.AddrPort, p pingPacket) peerState {
|
||||
if addr != s.routingData.remoteAddr {
|
||||
if addr != s.staged.remoteAddr {
|
||||
s.logf("Got new peer address: %v", addr)
|
||||
s.routingData.remoteAddr = addr
|
||||
s.routingData.up = true
|
||||
s.staged.remoteAddr = addr
|
||||
s.staged.up = true
|
||||
s.publish()
|
||||
}
|
||||
|
||||
if s.routingData.dataCipher == nil || p.SharedKey != s.routingData.dataCipher.Key() {
|
||||
if s.staged.dataCipher == nil || p.SharedKey != s.staged.dataCipher.Key() {
|
||||
s.logf("Got new shared key.")
|
||||
s.routingData.dataCipher = newDataCipherFromKey(p.SharedKey)
|
||||
s.routingData.up = true
|
||||
s.staged.dataCipher = newDataCipherFromKey(p.SharedKey)
|
||||
s.staged.up = true
|
||||
s.publish()
|
||||
}
|
||||
|
||||
@ -252,13 +267,13 @@ type stateSelectRelay struct {
|
||||
|
||||
func newStateSelectRelay(b *stateBase) peerState {
|
||||
s := &stateSelectRelay{stateBase: b}
|
||||
s.routingData.dataCipher = nil
|
||||
s.routingData.up = false
|
||||
s.staged.dataCipher = nil
|
||||
s.staged.up = false
|
||||
s.publish()
|
||||
|
||||
if relay := s.selectRelay(); relay != 0 {
|
||||
s.routingData.up = false
|
||||
s.routingData.relayIP = relay
|
||||
s.staged.up = false
|
||||
s.staged.relayIP = relay
|
||||
return s.selectRole()
|
||||
}
|
||||
|
||||
@ -278,7 +293,8 @@ func (s *stateSelectRelay) Name() string { return "select-relay" }
|
||||
|
||||
func (s *stateSelectRelay) OnPingTimer() peerState {
|
||||
if relay := s.selectRelay(); relay != 0 {
|
||||
s.routingData.relayIP = relay
|
||||
s.logf("Got relay IP: %d", relay)
|
||||
s.staged.relayIP = relay
|
||||
return s.selectRole()
|
||||
}
|
||||
s.resetPingTimer()
|
||||
@ -295,8 +311,8 @@ type stateClientRelayed struct {
|
||||
func newStateClientRelayed(b *stateBase) peerState {
|
||||
s := &stateClientRelayed{stateBase: b}
|
||||
|
||||
s.routingData.dataCipher = newDataCipher()
|
||||
s.sharedKey = s.routingData.dataCipher.Key()
|
||||
s.staged.dataCipher = newDataCipher()
|
||||
s.sharedKey = s.staged.dataCipher.Key()
|
||||
s.publish()
|
||||
|
||||
s.sendPing(s.sharedKey)
|
||||
@ -308,10 +324,11 @@ func newStateClientRelayed(b *stateBase) peerState {
|
||||
func (s *stateClientRelayed) Name() string { return "client-relayed" }
|
||||
|
||||
func (s *stateClientRelayed) OnPong(addr netip.AddrPort, p pongPacket) peerState {
|
||||
if !s.routingData.up {
|
||||
s.routingData.up = true
|
||||
if !s.staged.up {
|
||||
s.staged.up = true
|
||||
s.publish()
|
||||
}
|
||||
|
||||
s.resetTimeoutTimer()
|
||||
return nil
|
||||
}
|
||||
@ -342,10 +359,10 @@ func newStateServerRelayed(b *stateBase) peerState {
|
||||
func (s *stateServerRelayed) Name() string { return "server-relayed" }
|
||||
|
||||
func (s *stateServerRelayed) OnPing(addr netip.AddrPort, p pingPacket) peerState {
|
||||
if s.routingData.dataCipher == nil || p.SharedKey != s.routingData.dataCipher.Key() {
|
||||
if s.staged.dataCipher == nil || p.SharedKey != s.staged.dataCipher.Key() {
|
||||
s.logf("Got new shared key.")
|
||||
s.routingData.up = true
|
||||
s.routingData.dataCipher = newDataCipherFromKey(p.SharedKey)
|
||||
s.staged.up = true
|
||||
s.staged.dataCipher = newDataCipherFromKey(p.SharedKey)
|
||||
s.publish()
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,12 @@ func (rp *remotePeer) supervise(conf m.PeerConfig) {
|
||||
|
||||
case pkt := <-rp.controlPackets:
|
||||
switch p := pkt.Payload.(type) {
|
||||
case synPacket:
|
||||
nextState = curState.OnSyn(pkt.RemoteAddr, p)
|
||||
case synAckPacket:
|
||||
nextState = curState.OnSynAck(pkt.RemoteAddr, p)
|
||||
case ackPacket:
|
||||
nextState = curState.OnAck(pkt.RemoteAddr, p)
|
||||
case pingPacket:
|
||||
nextState = curState.OnPing(pkt.RemoteAddr, p)
|
||||
case pongPacket:
|
||||
|
Loading…
x
Reference in New Issue
Block a user