104 lines
1.9 KiB
Go
104 lines
1.9 KiB
Go
package peer
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/netip"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type IFReader struct {
|
|
iface io.Reader
|
|
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error)
|
|
rt *atomic.Pointer[routingTable]
|
|
buf1 []byte
|
|
buf2 []byte
|
|
}
|
|
|
|
func NewIFReader(
|
|
iface io.Reader,
|
|
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error),
|
|
rt *atomic.Pointer[routingTable],
|
|
) *IFReader {
|
|
return &IFReader{iface, writeToUDPAddrPort, rt, newBuf(), newBuf()}
|
|
}
|
|
|
|
func (r *IFReader) Run() {
|
|
packet := newBuf()
|
|
for {
|
|
r.handleNextPacket(packet)
|
|
}
|
|
}
|
|
|
|
func (r *IFReader) handleNextPacket(packet []byte) {
|
|
packet = r.readNextPacket(packet)
|
|
remoteIP, ok := r.parsePacket(packet)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
rt := r.rt.Load()
|
|
peer := rt.Peers[remoteIP]
|
|
if !peer.Up {
|
|
r.logf("Peer %d not up.", peer.IP)
|
|
return
|
|
}
|
|
|
|
enc := peer.EncryptDataPacket(peer.IP, packet, r.buf1)
|
|
if peer.Direct {
|
|
r.writeToUDPAddrPort(enc, peer.DirectAddr)
|
|
return
|
|
}
|
|
|
|
relay, ok := rt.GetRelay()
|
|
if !ok {
|
|
r.logf("Relay not available for peer %d.", peer.IP)
|
|
return
|
|
}
|
|
|
|
enc = relay.EncryptDataPacket(peer.IP, enc, r.buf2)
|
|
r.writeToUDPAddrPort(enc, relay.DirectAddr)
|
|
}
|
|
|
|
func (r *IFReader) readNextPacket(buf []byte) []byte {
|
|
n, err := r.iface.Read(buf[:cap(buf)])
|
|
if err != nil {
|
|
log.Fatalf("Failed to read from interface: %v", err)
|
|
}
|
|
|
|
return buf[:n]
|
|
}
|
|
|
|
func (r *IFReader) parsePacket(buf []byte) (byte, bool) {
|
|
n := len(buf)
|
|
if n == 0 {
|
|
return 0, false
|
|
}
|
|
|
|
version := buf[0] >> 4
|
|
|
|
switch version {
|
|
case 4:
|
|
if n < 20 {
|
|
r.logf("Short IPv4 packet: %d", len(buf))
|
|
return 0, false
|
|
}
|
|
return buf[19], true
|
|
|
|
case 6:
|
|
if len(buf) < 40 {
|
|
r.logf("Short IPv6 packet: %d", len(buf))
|
|
return 0, false
|
|
}
|
|
return buf[39], true
|
|
|
|
default:
|
|
r.logf("Invalid IP packet version: %v", version)
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
func (*IFReader) logf(s string, args ...any) {
|
|
log.Printf("[IFReader] "+s, args...)
|
|
}
|