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