WIP: cleanup. Local peer discovery working.
This commit is contained in:
@@ -13,21 +13,17 @@ func addrDiscoveryServer() {
|
||||
)
|
||||
|
||||
for {
|
||||
pkt := <-discoveryPackets
|
||||
msg := <-discoveryMessages
|
||||
p := msg.Packet
|
||||
|
||||
p, ok := pkt.Payload.(addrDiscoveryPacket)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
route := routingTable[pkt.SrcIP].Load()
|
||||
route := routingTable[msg.SrcIP].Load()
|
||||
if route == nil || !route.RemoteAddr.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
_sendControlPacket(addrDiscoveryPacket{
|
||||
TraceID: p.TraceID,
|
||||
ToAddr: pkt.SrcAddr,
|
||||
ToAddr: msg.SrcAddr,
|
||||
}, *route, buf1, buf2)
|
||||
}
|
||||
}
|
||||
@@ -46,9 +42,9 @@ func addrDiscoveryClient() {
|
||||
|
||||
for {
|
||||
select {
|
||||
case pkt := <-discoveryPackets:
|
||||
p, ok := pkt.Payload.(addrDiscoveryPacket)
|
||||
if !ok || p.TraceID != addrPacket.TraceID || !p.ToAddr.IsValid() || p.ToAddr == lAddr {
|
||||
case msg := <-discoveryMessages:
|
||||
p := msg.Packet
|
||||
if p.TraceID != addrPacket.TraceID || !p.ToAddr.IsValid() || p.ToAddr == lAddr {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
go build
|
||||
sudo setcap cap_net_admin+iep ./client
|
||||
./client 144.76.78.93
|
||||
@@ -1,15 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"vppn/node"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
log.Fatalf("Usage: %s <addr:port>", os.Args[0])
|
||||
}
|
||||
n := node.NewTmpNodeClient(os.Args[1])
|
||||
n.RunClient()
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
go build
|
||||
ssh kevin "killall server"
|
||||
scp server kevin:/home/jdl/tmp/
|
||||
ssh root@kevin "sudo setcap cap_net_admin+iep /home/jdl/tmp/server"
|
||||
ssh kevin "/home/jdl/tmp/server"
|
||||
@@ -1,8 +0,0 @@
|
||||
package main
|
||||
|
||||
import "vppn/node"
|
||||
|
||||
func main() {
|
||||
n := node.NewTmpNodeServer()
|
||||
n.RunServer()
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"vppn/m"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -13,6 +13,12 @@ const (
|
||||
if_queue_len = 2048
|
||||
controlCipherOverhead = 16
|
||||
dataCipherOverhead = 16
|
||||
signOverhead = 64
|
||||
)
|
||||
|
||||
var (
|
||||
multicastIP = netip.AddrFrom4([4]byte{224, 0, 0, 157})
|
||||
multicastAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(multicastIP, 4560))
|
||||
)
|
||||
|
||||
type peerRoute struct {
|
||||
@@ -56,18 +62,9 @@ var (
|
||||
return
|
||||
}()
|
||||
|
||||
// Channels for incoming control packets.
|
||||
controlPackets [256]chan controlPacket = func() (out [256]chan controlPacket) {
|
||||
messages [256]chan any = func() (out [256]chan any) {
|
||||
for i := range out {
|
||||
out[i] = make(chan controlPacket, 256)
|
||||
}
|
||||
return
|
||||
}()
|
||||
|
||||
// Channels for incoming peer updates from the hub.
|
||||
peerUpdates [256]chan *m.Peer = func() (out [256]chan *m.Peer) {
|
||||
for i := range out {
|
||||
out[i] = make(chan *m.Peer)
|
||||
out[i] = make(chan any, 256)
|
||||
}
|
||||
return
|
||||
}()
|
||||
@@ -81,8 +78,10 @@ var (
|
||||
return
|
||||
}()
|
||||
|
||||
// Managed by the addrDiscovery* functions.
|
||||
discoveryMessages = make(chan controlMsg[addrDiscoveryPacket], 256)
|
||||
|
||||
// Managed by the relayManager.
|
||||
discoveryPackets = make(chan controlPacket, 256)
|
||||
localAddr = &atomic.Pointer[netip.AddrPort]{}
|
||||
relayIP = &atomic.Pointer[byte]{}
|
||||
localAddr = &atomic.Pointer[netip.AddrPort]{}
|
||||
relayIP = &atomic.Pointer[byte]{}
|
||||
)
|
||||
|
||||
@@ -86,7 +86,7 @@ func (hp *hubPoller) applyNetworkState(state m.NetworkState) {
|
||||
for i, peer := range state.Peers {
|
||||
if i != int(localIP) {
|
||||
if peer != nil && peer.Version != hp.versions[i] {
|
||||
peerUpdates[i] <- state.Peers[i]
|
||||
messages[i] <- peerUpdateMsg{Peer: state.Peers[i]}
|
||||
hp.versions[i] = peer.Version
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
)
|
||||
|
||||
func localBroadcaster() {
|
||||
var (
|
||||
buf1 = make([]byte, bufferSize)
|
||||
buf2 = make([]byte, bufferSize)
|
||||
)
|
||||
time.Sleep(4 * time.Second)
|
||||
doBroadcast(buf1, buf2)
|
||||
for range time.Tick(32 * time.Second) {
|
||||
doBroadcast(buf1, buf2)
|
||||
}
|
||||
}
|
||||
|
||||
func doBroadcast(buf1, buf2 []byte) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
log.Printf("Failed to list interfaces: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagRunning == 0 {
|
||||
continue
|
||||
}
|
||||
if iface.Flags&net.FlagPointToPoint != 0 {
|
||||
continue
|
||||
}
|
||||
if iface.Flags&net.FlagBroadcast == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
log.Printf("Failed to get interface addresses: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipNet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ip4 := ipNet.IP.To4()
|
||||
if ip4 == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ip, ok := lastAddr(ipNet)
|
||||
if !ok {
|
||||
log.Printf("Failed to find broadcast address: %v", ipNet)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("Broadcasting on address: %v", ip)
|
||||
//addr := netip.AddrPortFrom(ip, 456)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// works when the n is a prefix, otherwise...
|
||||
func lastAddr(n *net.IPNet) (netip.Addr, bool) {
|
||||
ip := make(net.IP, len(n.IP.To4()))
|
||||
binary.BigEndian.PutUint32(ip, binary.BigEndian.Uint32(n.IP.To4())|
|
||||
^binary.BigEndian.Uint32(net.IP(n.Mask).To4()))
|
||||
return netip.AddrFromSlice(ip)
|
||||
}
|
||||
@@ -3,18 +3,11 @@ package node
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/nacl/sign"
|
||||
)
|
||||
|
||||
var (
|
||||
signOverhead = 64
|
||||
multicastIP = netip.AddrFrom4([4]byte{224, 0, 0, 157})
|
||||
multicastAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(multicastIP, 4560))
|
||||
)
|
||||
|
||||
func localDiscovery() {
|
||||
conn, err := net.ListenMulticastUDP("udp", nil, multicastAddr)
|
||||
if err != nil {
|
||||
@@ -32,8 +25,9 @@ func sendLocalDiscovery(conn *net.UDPConn) {
|
||||
buf2 = make([]byte, bufferSize)
|
||||
)
|
||||
|
||||
for range time.Tick(16 * time.Second) {
|
||||
for range time.Tick(32 * time.Second) {
|
||||
signed := buildLocalDiscoveryPacket(buf1, buf2)
|
||||
log.Printf("Sending discovery packet...")
|
||||
if _, err := conn.WriteToUDP(signed, multicastAddr); err != nil {
|
||||
log.Printf("Failed to write multicast UDP packet: %v", err)
|
||||
}
|
||||
@@ -51,21 +45,24 @@ func recvLocalDiscovery(conn *net.UDPConn) {
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read from UDP port (multicast): %v", err)
|
||||
}
|
||||
log.Printf("Got local discovery packet...")
|
||||
|
||||
raw = raw[:n]
|
||||
h, ok := openLocalDiscoveryPacket(raw, buf)
|
||||
if !ok {
|
||||
log.Printf("Failed to open discovery packet?")
|
||||
continue
|
||||
}
|
||||
|
||||
pkt := controlPacket{
|
||||
msg := controlMsg[localDiscoveryPacket]{
|
||||
SrcIP: h.SourceIP,
|
||||
SrcAddr: remoteAddr,
|
||||
Payload: localDiscoveryPacket{},
|
||||
Packet: localDiscoveryPacket{},
|
||||
}
|
||||
log.Printf("Got local discovery packet from %d/%v...", h.SourceIP, remoteAddr)
|
||||
|
||||
select {
|
||||
case controlPackets[h.SourceIP] <- pkt:
|
||||
case messages[h.SourceIP] <- msg:
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -92,6 +89,7 @@ func openLocalDiscoveryPacket(raw, buf []byte) (h header, ok bool) {
|
||||
h.Parse(raw[signOverhead:])
|
||||
route := routingTable[h.SourceIP].Load()
|
||||
if route == nil || route.PubSignKey == nil {
|
||||
log.Printf("Missing signing key")
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
|
||||
62
node/main.go
62
node/main.go
@@ -11,6 +11,7 @@ import (
|
||||
"net/netip"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
"vppn/m"
|
||||
)
|
||||
|
||||
@@ -26,13 +27,11 @@ func Main() {
|
||||
var (
|
||||
initURL string
|
||||
listenIP string
|
||||
port int
|
||||
)
|
||||
|
||||
flag.StringVar(&netName, "name", "", "[REQUIRED] The network name.")
|
||||
flag.StringVar(&initURL, "init-url", "", "Initializes peer from the hub URL.")
|
||||
flag.StringVar(&listenIP, "listen-ip", "", "IP address to listen on.")
|
||||
flag.IntVar(&port, "port", 0, "Port to listen on.")
|
||||
flag.Parse()
|
||||
|
||||
if netName == "" {
|
||||
@@ -45,7 +44,7 @@ func Main() {
|
||||
return
|
||||
}
|
||||
|
||||
main(listenIP, uint16(port))
|
||||
main(listenIP)
|
||||
}
|
||||
|
||||
func mainInit(initURL string) {
|
||||
@@ -74,20 +73,18 @@ func mainInit(initURL string) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func main(listenIP string, port uint16) {
|
||||
func main(listenIP string) {
|
||||
config, err := loadPeerConfig(netName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load configuration: %v", err)
|
||||
}
|
||||
|
||||
port = determinePort(config.Port, port)
|
||||
|
||||
iface, err := openInterface(config.Network, config.PeerIP, netName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open interface: %v", err)
|
||||
}
|
||||
|
||||
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", listenIP, port))
|
||||
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", listenIP, config.Port))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to resolve UDP address: %v", err)
|
||||
}
|
||||
@@ -129,6 +126,17 @@ func main(listenIP string, port uint16) {
|
||||
go localDiscovery()
|
||||
}
|
||||
|
||||
go func() {
|
||||
for range time.Tick(pingInterval) {
|
||||
for i := range messages {
|
||||
select {
|
||||
case messages[i] <- pingTimerMsg{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go newHubPoller(config).Run()
|
||||
go readFromConn(conn)
|
||||
readFromIFace(iface)
|
||||
@@ -136,18 +144,6 @@ func main(listenIP string, port uint16) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func determinePort(confPort, portFromCommandLine uint16) uint16 {
|
||||
if portFromCommandLine != 0 {
|
||||
return portFromCommandLine
|
||||
}
|
||||
if confPort != 0 {
|
||||
return confPort
|
||||
}
|
||||
return 456
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func readFromConn(conn *net.UDPConn) {
|
||||
|
||||
defer panicHandler()
|
||||
@@ -218,31 +214,21 @@ func handleControlPacket(addr netip.AddrPort, h header, data, decBuf []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
pkt := controlPacket{
|
||||
SrcIP: h.SourceIP,
|
||||
SrcAddr: addr,
|
||||
}
|
||||
|
||||
if err := pkt.ParsePayload(out); err != nil {
|
||||
msg, err := parseControlMsg(h.SourceIP, addr, out)
|
||||
if err != nil {
|
||||
log.Printf("Failed to parse control packet: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch pkt.Payload.(type) {
|
||||
|
||||
case addrDiscoveryPacket:
|
||||
select {
|
||||
case discoveryPackets <- pkt:
|
||||
default:
|
||||
log.Printf("Dropping discovery packet.")
|
||||
}
|
||||
if dm, ok := msg.(controlMsg[addrDiscoveryPacket]); ok {
|
||||
discoveryMessages <- dm
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case messages[h.SourceIP] <- msg:
|
||||
default:
|
||||
select {
|
||||
case controlPackets[h.SourceIP] <- pkt:
|
||||
default:
|
||||
log.Printf("Dropping control packet.")
|
||||
}
|
||||
log.Printf("Dropping control packet.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1,66 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"vppn/m"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type controlMsg[T any] struct {
|
||||
SrcIP byte
|
||||
SrcAddr netip.AddrPort
|
||||
Packet T
|
||||
}
|
||||
|
||||
func parseControlMsg(srcIP byte, srcAddr netip.AddrPort, buf []byte) (any, error) {
|
||||
switch buf[0] {
|
||||
|
||||
case packetTypeSyn:
|
||||
packet, err := parseSynPacket(buf)
|
||||
return controlMsg[synPacket]{
|
||||
SrcIP: srcIP,
|
||||
SrcAddr: srcAddr,
|
||||
Packet: packet,
|
||||
}, err
|
||||
|
||||
case packetTypeSynAck:
|
||||
packet, err := parseSynAckPacket(buf)
|
||||
return controlMsg[synAckPacket]{
|
||||
SrcIP: srcIP,
|
||||
SrcAddr: srcAddr,
|
||||
Packet: packet,
|
||||
}, err
|
||||
|
||||
case packetTypeProbe:
|
||||
packet, err := parseProbePacket(buf)
|
||||
return controlMsg[probePacket]{
|
||||
SrcIP: srcIP,
|
||||
SrcAddr: srcAddr,
|
||||
Packet: packet,
|
||||
}, err
|
||||
|
||||
case packetTypeAddrDiscovery:
|
||||
packet, err := parseAddrDiscoveryPacket(buf)
|
||||
return controlMsg[addrDiscoveryPacket]{
|
||||
SrcIP: srcIP,
|
||||
SrcAddr: srcAddr,
|
||||
Packet: packet,
|
||||
}, err
|
||||
|
||||
default:
|
||||
return nil, errUnknownPacketType
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type peerUpdateMsg struct {
|
||||
Peer *m.Peer
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type pingTimerMsg struct{}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -20,30 +20,6 @@ const (
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type controlPacket struct {
|
||||
SrcIP byte
|
||||
SrcAddr netip.AddrPort
|
||||
Payload any
|
||||
}
|
||||
|
||||
func (p *controlPacket) ParsePayload(buf []byte) (err error) {
|
||||
switch buf[0] {
|
||||
case packetTypeSyn:
|
||||
p.Payload, err = parseSynPacket(buf)
|
||||
case packetTypeSynAck:
|
||||
p.Payload, err = parseSynAckPacket(buf)
|
||||
case packetTypeProbe:
|
||||
p.Payload, err = parseProbePacket(buf)
|
||||
case packetTypeAddrDiscovery:
|
||||
p.Payload, err = parseAddrDiscoveryPacket(buf)
|
||||
default:
|
||||
return errUnknownPacketType
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type synPacket struct {
|
||||
TraceID uint64 // TraceID to match response w/ request.
|
||||
SharedKey [32]byte // Our shared key.
|
||||
|
||||
@@ -29,8 +29,7 @@ type peerSupervisor struct {
|
||||
remotePub bool
|
||||
|
||||
// Incoming events.
|
||||
peerUpdates chan *m.Peer
|
||||
controlPackets chan controlPacket
|
||||
messages chan any
|
||||
|
||||
// Buffers for sending control packets.
|
||||
buf1 []byte
|
||||
@@ -39,12 +38,11 @@ type peerSupervisor struct {
|
||||
|
||||
func newPeerSupervisor(i int) *peerSupervisor {
|
||||
return &peerSupervisor{
|
||||
published: routingTable[i],
|
||||
remoteIP: byte(i),
|
||||
peerUpdates: peerUpdates[i],
|
||||
controlPackets: controlPackets[i],
|
||||
buf1: make([]byte, bufferSize),
|
||||
buf2: make([]byte, bufferSize),
|
||||
published: routingTable[i],
|
||||
remoteIP: byte(i),
|
||||
messages: messages[i],
|
||||
buf1: make([]byte, bufferSize),
|
||||
buf2: make([]byte, bufferSize),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +93,12 @@ func (s *peerSupervisor) publish() {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func (s *peerSupervisor) noPeer() stateFunc {
|
||||
return s.peerUpdate(<-s.peerUpdates)
|
||||
for {
|
||||
rawMsg := <-s.messages
|
||||
if msg, ok := rawMsg.(peerUpdateMsg); ok {
|
||||
return s.peerUpdate(msg.Peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -149,75 +152,73 @@ func (s *peerSupervisor) server() stateFunc {
|
||||
logf("DOWN")
|
||||
|
||||
var (
|
||||
syn synPacket
|
||||
timeoutTimer = time.NewTimer(timeoutInterval)
|
||||
syn synPacket
|
||||
lastSeen = time.Now()
|
||||
)
|
||||
|
||||
// Timer will be restarted once we have established a connection.
|
||||
timeoutTimer.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case peer := <-s.peerUpdates:
|
||||
return s.peerUpdate(peer)
|
||||
rawMsg := <-s.messages
|
||||
switch msg := rawMsg.(type) {
|
||||
|
||||
case pkt := <-s.controlPackets:
|
||||
switch p := pkt.Payload.(type) {
|
||||
case peerUpdateMsg:
|
||||
return s.peerUpdate(msg.Peer)
|
||||
|
||||
case synPacket:
|
||||
timeoutTimer.Reset(timeoutInterval)
|
||||
case controlMsg[synPacket]:
|
||||
p := msg.Packet
|
||||
lastSeen = time.Now()
|
||||
|
||||
// Before we can respond to this packet, we need to make sure the
|
||||
// route is setup properly.
|
||||
//
|
||||
// The client will update the syn's TraceID whenever there's a change.
|
||||
// The server will follow the client's request.
|
||||
if p.TraceID != syn.TraceID || !s.staged.Up {
|
||||
if p.Direct {
|
||||
logf("UP - Direct")
|
||||
} else {
|
||||
logf("UP - Relayed")
|
||||
}
|
||||
|
||||
syn = p
|
||||
s.staged.Up = true
|
||||
s.staged.Direct = syn.Direct
|
||||
s.staged.DataCipher = newDataCipherFromKey(syn.SharedKey)
|
||||
s.staged.RemoteAddr = pkt.SrcAddr
|
||||
|
||||
s.publish()
|
||||
}
|
||||
|
||||
// We should always respond.
|
||||
ack := synAckPacket{
|
||||
TraceID: syn.TraceID,
|
||||
FromAddr: getLocalAddr(),
|
||||
}
|
||||
s.sendControlPacket(ack)
|
||||
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
}
|
||||
|
||||
if !syn.FromAddr.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
probe := probePacket{TraceID: newTraceID()}
|
||||
s.sendControlPacketTo(probe, syn.FromAddr)
|
||||
|
||||
case probePacket:
|
||||
if pkt.SrcAddr.IsValid() {
|
||||
s.sendControlPacketTo(probePacket{TraceID: p.TraceID}, pkt.SrcAddr)
|
||||
// Before we can respond to this packet, we need to make sure the
|
||||
// route is setup properly.
|
||||
//
|
||||
// The client will update the syn's TraceID whenever there's a change.
|
||||
// The server will follow the client's request.
|
||||
if p.TraceID != syn.TraceID || !s.staged.Up {
|
||||
if p.Direct {
|
||||
logf("UP - Direct")
|
||||
} else {
|
||||
logf("Invalid probe address")
|
||||
logf("UP - Relayed")
|
||||
}
|
||||
|
||||
syn = p
|
||||
s.staged.Up = true
|
||||
s.staged.Direct = syn.Direct
|
||||
s.staged.DataCipher = newDataCipherFromKey(syn.SharedKey)
|
||||
s.staged.RemoteAddr = msg.SrcAddr
|
||||
|
||||
s.publish()
|
||||
}
|
||||
|
||||
case <-timeoutTimer.C:
|
||||
logf("Connection timeout")
|
||||
s.staged.Up = false
|
||||
s.publish()
|
||||
// We should always respond.
|
||||
ack := synAckPacket{
|
||||
TraceID: syn.TraceID,
|
||||
FromAddr: getLocalAddr(),
|
||||
}
|
||||
s.sendControlPacket(ack)
|
||||
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
}
|
||||
|
||||
if !syn.FromAddr.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
probe := probePacket{TraceID: newTraceID()}
|
||||
s.sendControlPacketTo(probe, syn.FromAddr)
|
||||
|
||||
case controlMsg[probePacket]:
|
||||
if !msg.SrcAddr.IsValid() {
|
||||
logf("Invalid probe address")
|
||||
continue
|
||||
}
|
||||
s.sendControlPacketTo(probePacket{TraceID: msg.Packet.TraceID}, msg.SrcAddr)
|
||||
|
||||
case pingTimerMsg:
|
||||
if time.Since(lastSeen) > timeoutInterval {
|
||||
logf("Connection timeout")
|
||||
s.staged.Up = false
|
||||
s.publish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,91 +238,106 @@ func (s *peerSupervisor) client() stateFunc {
|
||||
FromAddr: getLocalAddr(),
|
||||
}
|
||||
|
||||
ack synAckPacket
|
||||
lastSeen = time.Now()
|
||||
ack synAckPacket
|
||||
|
||||
probe probePacket
|
||||
probeAddr netip.AddrPort
|
||||
|
||||
remoteAddr netip.AddrPort
|
||||
localProbe probePacket
|
||||
localProbeAddr netip.AddrPort
|
||||
|
||||
timeoutTimer = time.NewTimer(timeoutInterval)
|
||||
pingTimer = time.NewTimer(pingInterval)
|
||||
lastLocalAddr netip.AddrPort
|
||||
)
|
||||
|
||||
defer timeoutTimer.Stop()
|
||||
defer pingTimer.Stop()
|
||||
|
||||
s.sendControlPacket(syn)
|
||||
|
||||
for {
|
||||
select {
|
||||
rawMsg := <-s.messages
|
||||
switch msg := rawMsg.(type) {
|
||||
|
||||
case peer := <-s.peerUpdates:
|
||||
return s.peerUpdate(peer)
|
||||
case peerUpdateMsg:
|
||||
return s.peerUpdate(msg.Peer)
|
||||
|
||||
case pkt := <-s.controlPackets:
|
||||
switch p := pkt.Payload.(type) {
|
||||
case controlMsg[synAckPacket]:
|
||||
p := msg.Packet
|
||||
|
||||
case synAckPacket:
|
||||
if p.TraceID != syn.TraceID {
|
||||
continue // Hmm...
|
||||
}
|
||||
if p.TraceID != syn.TraceID {
|
||||
continue // Hmm...
|
||||
}
|
||||
|
||||
ack = p
|
||||
timeoutTimer.Reset(timeoutInterval)
|
||||
lastSeen = time.Now()
|
||||
ack = msg.Packet
|
||||
|
||||
if !s.staged.Up {
|
||||
if s.staged.Direct {
|
||||
logf("UP - Direct")
|
||||
} else {
|
||||
logf("UP - Relayed")
|
||||
}
|
||||
|
||||
s.staged.Up = true
|
||||
s.publish()
|
||||
}
|
||||
|
||||
case probePacket:
|
||||
if !s.staged.Up {
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
logf("UP - Direct")
|
||||
} else {
|
||||
logf("UP - Relayed")
|
||||
}
|
||||
|
||||
if p.TraceID != probe.TraceID {
|
||||
continue
|
||||
}
|
||||
|
||||
// Upgrade connection.
|
||||
|
||||
logf("UP - Direct")
|
||||
s.staged.Direct = true
|
||||
s.staged.RemoteAddr = probeAddr
|
||||
s.staged.Up = true
|
||||
s.publish()
|
||||
|
||||
syn.TraceID = newTraceID()
|
||||
syn.Direct = true
|
||||
syn.FromAddr = getLocalAddr()
|
||||
s.sendControlPacket(syn)
|
||||
}
|
||||
|
||||
case <-pingTimer.C:
|
||||
// Send syn.
|
||||
|
||||
syn.FromAddr = getLocalAddr()
|
||||
if syn.FromAddr != remoteAddr {
|
||||
syn.TraceID = newTraceID()
|
||||
remoteAddr = syn.FromAddr
|
||||
}
|
||||
|
||||
s.sendControlPacket(syn)
|
||||
|
||||
pingTimer.Reset(pingInterval)
|
||||
|
||||
case controlMsg[probePacket]:
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: Check if we have local address.
|
||||
// TODO: Send local probe
|
||||
p := msg.Packet
|
||||
|
||||
if p.TraceID != localProbe.TraceID && p.TraceID != probe.TraceID {
|
||||
continue
|
||||
}
|
||||
|
||||
// Upgrade connection.
|
||||
|
||||
s.staged.Direct = true
|
||||
if p.TraceID == localProbe.TraceID {
|
||||
logf("UP - Local")
|
||||
s.staged.RemoteAddr = localProbeAddr
|
||||
} else {
|
||||
logf("UP - Direct")
|
||||
s.staged.RemoteAddr = probeAddr
|
||||
}
|
||||
s.publish()
|
||||
|
||||
syn.TraceID = newTraceID()
|
||||
syn.Direct = true
|
||||
syn.FromAddr = getLocalAddr()
|
||||
s.sendControlPacket(syn)
|
||||
|
||||
case controlMsg[localDiscoveryPacket]:
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
}
|
||||
|
||||
// Send probe.
|
||||
//
|
||||
// The source port will be the multicast port, so we'll have to
|
||||
// construct the correct address using the peer's listed port.
|
||||
localProbe = probePacket{TraceID: newTraceID()}
|
||||
localProbeAddr = netip.AddrPortFrom(msg.SrcAddr.Addr(), s.peer.Port)
|
||||
s.sendControlPacketTo(localProbe, localProbeAddr)
|
||||
|
||||
case pingTimerMsg:
|
||||
if time.Since(lastSeen) > timeoutInterval {
|
||||
logf("Connection timeout")
|
||||
return s.peerUpdate(s.peer)
|
||||
}
|
||||
|
||||
syn.FromAddr = getLocalAddr()
|
||||
if syn.FromAddr != lastLocalAddr {
|
||||
syn.TraceID = newTraceID()
|
||||
lastLocalAddr = syn.FromAddr
|
||||
}
|
||||
|
||||
s.sendControlPacket(syn)
|
||||
|
||||
if s.staged.Direct {
|
||||
continue
|
||||
}
|
||||
|
||||
if !ack.FromAddr.IsValid() {
|
||||
continue
|
||||
@@ -331,10 +347,6 @@ func (s *peerSupervisor) client() stateFunc {
|
||||
probeAddr = ack.FromAddr
|
||||
|
||||
s.sendControlPacketTo(probe, ack.FromAddr)
|
||||
|
||||
case <-timeoutTimer.C:
|
||||
logf("Connection timeout")
|
||||
return s.peerUpdate(s.peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package node
|
||||
Reference in New Issue
Block a user