FOrwarding is working. Not well at the moment.

This commit is contained in:
jdl 2024-12-18 13:29:06 +01:00
parent 6e3c3ec0b2
commit 2a1c809731
5 changed files with 119 additions and 43 deletions

View File

@ -14,6 +14,7 @@ type connWriter struct {
lock sync.Mutex lock sync.Mutex
localIP byte localIP byte
buf []byte buf []byte
buf2 []byte
counters [256]uint64 counters [256]uint64
routing *routingTable routing *routingTable
} }
@ -23,6 +24,7 @@ func newConnWriter(conn *net.UDPConn, localIP byte, routing *routingTable) *conn
UDPConn: conn, UDPConn: conn,
localIP: localIP, localIP: localIP,
buf: make([]byte, bufferSize), buf: make([]byte, bufferSize),
buf2: make([]byte, bufferSize),
routing: routing, routing: routing,
} }
@ -33,37 +35,76 @@ func newConnWriter(conn *net.UDPConn, localIP byte, routing *routingTable) *conn
return w return w
} }
func (w *connWriter) WriteTo(remoteIP, stream byte, data []byte) error { func (w *connWriter) WriteTo(remoteIP, stream byte, data []byte) {
// TODO: Handle mediator. dstPeer := w.routing.Get(remoteIP)
peer := w.routing.Get(remoteIP) if dstPeer == nil {
if peer == nil || peer.Addr == nil {
log.Printf("No peer: %d", remoteIP) log.Printf("No peer: %d", remoteIP)
return nil return
} }
if stream == streamData && !peer.Up { if stream == streamData && !dstPeer.Up {
log.Printf("Peer down: %d", remoteIP) log.Printf("Peer down: %d", remoteIP)
} return
return w.WriteToPeer(peer, stream, data)
} }
func (w *connWriter) WriteToPeer(peer *peer, stream byte, data []byte) error { var viaPeer *peer
if dstPeer.Mediated {
viaPeer = w.routing.mediator.Load()
if viaPeer == nil || viaPeer.Addr == nil {
log.Printf("Mediator not connected")
return
}
} else if dstPeer.Addr == nil {
log.Printf("Peer doesn't have address: %d", remoteIP)
return
}
w.WriteToPeer(dstPeer, viaPeer, stream, data)
}
func (w *connWriter) WriteToPeer(dstPeer, viaPeer *peer, stream byte, data []byte) {
w.lock.Lock() w.lock.Lock()
remoteIP := peer.IP addr := dstPeer.Addr
h := header{ h := header{
Counter: atomic.AddUint64(&w.counters[remoteIP], 1), Counter: atomic.AddUint64(&w.counters[dstPeer.IP], 1),
SourceIP: w.localIP, SourceIP: w.localIP,
ViaIP: 0, DestIP: dstPeer.IP,
DestIP: remoteIP,
Stream: stream, Stream: stream,
} }
buf := encryptPacket(&h, peer.SharedKey, data, w.buf) buf := encryptPacket(&h, dstPeer.SharedKey, data, w.buf)
_, err := w.WriteToUDPAddrPort(buf, *peer.Addr) if viaPeer != nil {
h := header{
Counter: atomic.AddUint64(&w.counters[viaPeer.IP], 1),
SourceIP: w.localIP,
DestIP: dstPeer.IP,
Forward: 1,
Stream: stream,
}
buf = encryptPacket(&h, viaPeer.SharedKey, buf, w.buf2)
addr = viaPeer.Addr
}
if _, err := w.WriteToUDPAddrPort(buf, *addr); err != nil {
log.Fatalf("Failed to write to UDP port: %v", err)
}
w.lock.Unlock() w.lock.Unlock()
return err }
func (w *connWriter) Forward(dstIP byte, packet []byte) {
dstPeer := w.routing.Get(dstIP)
if dstPeer == nil || dstPeer.Addr == nil {
log.Printf("No peer: %d", dstIP)
return
}
if _, err := w.WriteToUDPAddrPort(packet, *dstPeer.Addr); err != nil {
log.Fatalf("Failed to write to UDP port: %v", err)
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -89,38 +130,37 @@ func newConnReader(conn *net.UDPConn, localIP byte, routing *routingTable) *conn
return r return r
} }
func (r *connReader) Read(buf []byte) (remoteAddr netip.AddrPort, h header, data []byte, err error) { func (r *connReader) Read(buf []byte) (remoteAddr netip.AddrPort, h header, data []byte) {
var n int var (
n int
err error
)
for { for {
n, remoteAddr, err = r.ReadFromUDPAddrPort(buf[:bufferSize]) n, remoteAddr, err = r.ReadFromUDPAddrPort(buf[:bufferSize])
if err != nil { if err != nil {
return log.Fatalf("Failed to read from UDP port: %v", err)
} }
data = buf[:n] data = buf[:n]
if n < headerSize { if n < headerSize {
log.Printf("Dropping short packet: %d", n)
continue // Packet it soo short. continue // Packet it soo short.
} }
h.Parse(data) h.Parse(data)
if len(data) != headerSize+int(h.DataSize) { if len(data) != headerSize+int(h.DataSize) {
log.Printf("Malformed packet: %d != %d", len(data), headerSize+int(h.DataSize)) continue // Invalid header.
continue
} }
peer := r.routing.Get(h.SourceIP) peer := r.routing.Get(h.SourceIP)
if peer == nil { if peer == nil {
log.Printf("No peer: %d...", h.SourceIP)
continue continue
} }
out, ok := decryptPacket(peer.SharedKey, data, r.buf) out, ok := decryptPacket(peer.SharedKey, data, r.buf)
if !ok { if !ok {
log.Printf("Decrypt failed...")
continue continue
} }

View File

@ -11,8 +11,8 @@ const (
type header struct { type header struct {
Counter uint64 // Init with fasttime.Now() << 30 to ensure monotonic. Counter uint64 // Init with fasttime.Now() << 30 to ensure monotonic.
SourceIP byte SourceIP byte
ViaIP byte
DestIP byte DestIP byte
Forward byte
Stream byte // See stream* constants. Stream byte // See stream* constants.
DataSize uint16 // Data size following associated data. DataSize uint16 // Data size following associated data.
} }
@ -20,8 +20,8 @@ type header struct {
func (hdr *header) Parse(nb []byte) { func (hdr *header) Parse(nb []byte) {
hdr.Counter = *(*uint64)(unsafe.Pointer(&nb[0])) hdr.Counter = *(*uint64)(unsafe.Pointer(&nb[0]))
hdr.SourceIP = nb[8] hdr.SourceIP = nb[8]
hdr.ViaIP = nb[9] hdr.DestIP = nb[9]
hdr.DestIP = nb[10] hdr.Forward = nb[10]
hdr.Stream = nb[11] hdr.Stream = nb[11]
hdr.DataSize = *(*uint16)(unsafe.Pointer(&nb[12])) hdr.DataSize = *(*uint16)(unsafe.Pointer(&nb[12]))
} }
@ -29,8 +29,8 @@ func (hdr *header) Parse(nb []byte) {
func (hdr header) Marshal(buf []byte) { func (hdr header) Marshal(buf []byte) {
*(*uint64)(unsafe.Pointer(&buf[0])) = hdr.Counter *(*uint64)(unsafe.Pointer(&buf[0])) = hdr.Counter
buf[8] = hdr.SourceIP buf[8] = hdr.SourceIP
buf[9] = hdr.ViaIP buf[9] = hdr.DestIP
buf[10] = hdr.DestIP buf[10] = hdr.Forward
buf[11] = hdr.Stream buf[11] = hdr.Stream
*(*uint16)(unsafe.Pointer(&buf[12])) = hdr.DataSize *(*uint16)(unsafe.Pointer(&buf[12])) = hdr.DataSize
} }

View File

@ -138,9 +138,11 @@ func nodeConnReader(r *connReader, w *connWriter, iface io.ReadWriteCloser, rout
) )
for { for {
remoteAddr, h, data, err = r.Read(buf) remoteAddr, h, data = r.Read(buf)
if err != nil {
log.Fatalf("Failed to read from UDP connection: %v", err) if h.Forward != 0 {
w.Forward(h.DestIP, data)
continue
} }
switch h.Stream { switch h.Stream {
@ -178,13 +180,9 @@ func nodeIFaceReader(w *connWriter, iface io.ReadWriteCloser, router *router) {
} }
if remoteIP == w.localIP { if remoteIP == w.localIP {
//log.Printf("Incoming packet for self: %x", packet) continue // Don't write to self.
//iface.Write(packet)
continue
} }
if err := w.WriteTo(remoteIP, streamData, packet); err != nil { w.WriteTo(remoteIP, streamData, packet)
log.Fatalf("Failed to write to network: %v", err)
}
} }
} }

View File

@ -14,6 +14,8 @@ import (
type peer struct { type peer struct {
Up bool // No data will be sent to peers that are down. Up bool // No data will be sent to peers that are down.
Mediator bool
Mediated bool
IP byte IP byte
Addr *netip.AddrPort // If we have direct connection, otherwise use mediator. Addr *netip.AddrPort // If we have direct connection, otherwise use mediator.
SharedKey []byte SharedKey []byte
@ -49,8 +51,8 @@ func (r *routingTable) Set(ip byte, p *peer) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
type router struct { type router struct {
netName string
*routingTable *routingTable
netName string
peerSupers [256]*peerSupervisor peerSupers [256]*peerSupervisor
} }
@ -68,7 +70,7 @@ func newRouter(netName string, conf m.PeerConfig, routingData *routingTable, w *
r.routingTable) r.routingTable)
} }
// TODO: Handle Mediator go r.selectMediator()
go r.pollHub(conf) go r.pollHub(conf)
return r return r
@ -111,7 +113,6 @@ func (r *router) pollHub(conf m.PeerConfig) {
} }
req.SetBasicAuth("", conf.APIKey) req.SetBasicAuth("", conf.APIKey)
// TODO: Before we start polling, load state from the file system.
state, err := loadNetworkState(r.netName) state, err := loadNetworkState(r.netName)
if err != nil { if err != nil {
log.Printf("Failed to load network state: %v", err) log.Printf("Failed to load network state: %v", err)
@ -161,3 +162,25 @@ func (r *router) applyNetworkState(conf m.PeerConfig, state m.NetworkState) {
} }
} }
} }
// ----------------------------------------------------------------------------
func (r *router) selectMediator() {
for range time.Tick(8 * time.Second) {
current := r.mediator.Load()
if current != nil && current.Up {
continue
}
for i := range r.table {
peer := r.table[i].Load()
if peer != nil && peer.Up && peer.Mediator {
log.Printf("Got mediator: %v", *peer)
r.mediator.Store(peer)
return
}
}
r.mediator.Store(nil)
}
}

View File

@ -37,6 +37,7 @@ type peerSupervisor struct {
version int64 // Ony accessed in HandlePeerUpdate. version int64 // Ony accessed in HandlePeerUpdate.
peer *m.Peer peer *m.Peer
remoteAddrPort *netip.AddrPort remoteAddrPort *netip.AddrPort
mediated bool
sharedKey []byte sharedKey []byte
// Used by our state functions. // Used by our state functions.
@ -94,7 +95,6 @@ func (s *peerSupervisor) HandlePeerUpdate(p *m.Peer) {
if p.Version == s.version { if p.Version == s.version {
return return
} }
s.logf("New peer version: %d", p.Version)
s.version = p.Version s.version = p.Version
} else { } else {
s.version = 0 s.version = 0
@ -154,6 +154,8 @@ func (s *peerSupervisor) stateSelectRole() stateFunc {
s.updateRoutingTable(false) s.updateRoutingTable(false)
if s.remoteAddrPort != nil { if s.remoteAddrPort != nil {
s.mediated = false
// If both remote and local are public, one side acts as client, and one // If both remote and local are public, one side acts as client, and one
// side as server. // side as server.
if s.localPublic && s.localIP < s.peer.PeerIP { if s.localPublic && s.localIP < s.peer.PeerIP {
@ -164,6 +166,7 @@ func (s *peerSupervisor) stateSelectRole() stateFunc {
// We're public, remote is not => can only wait for connection // We're public, remote is not => can only wait for connection
if s.localPublic { if s.localPublic {
s.mediated = false
return s.stateAccept return s.stateAccept
} }
@ -277,8 +280,18 @@ func (s *peerSupervisor) stateConnected() stateFunc {
func (s *peerSupervisor) stateMediated() stateFunc { func (s *peerSupervisor) stateMediated() stateFunc {
s.logf("STATE: Mediated") s.logf("STATE: Mediated")
// TODO s.mediated = true
select {} s.updateRoutingTable(true)
for {
select {
case <-s.packets:
// Drop.
case s.peer = <-s.peerUpdates:
s.logf("New peer: %v", s.peer)
return s.stateInit
}
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -290,6 +303,8 @@ func (s *peerSupervisor) clearRoutingTable() {
func (s *peerSupervisor) updateRoutingTable(up bool) { func (s *peerSupervisor) updateRoutingTable(up bool) {
s.table.Set(s.remoteIP, &peer{ s.table.Set(s.remoteIP, &peer{
Up: up, Up: up,
Mediator: s.peer.Mediator,
Mediated: s.mediated,
IP: s.remoteIP, IP: s.remoteIP,
Addr: s.remoteAddrPort, Addr: s.remoteAddrPort,
SharedKey: s.sharedKey, SharedKey: s.sharedKey,