vppn/peer/peer-ifreader.go
2024-12-08 09:45:29 +01:00

115 lines
2.2 KiB
Go

package peer
import (
"fmt"
"log"
"net"
"net/netip"
"runtime/debug"
"vppn/fasttime"
)
func (peer *Peer) ifReader() {
defer func() {
if r := recover(); r != nil {
fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
}
}()
var (
n int
destIP byte
router = peer.router
route *route
iface = peer.iface
nonce = Nonce{
SourceIP: peer.ip,
PacketType: PACKET_TYPE_DATA,
StreamID: STREAM_DATA,
}
err error
now uint64
counterTS uint64
counter uint64
packet = make([]byte, BUFFER_SIZE)
encrypted = make([]byte, BUFFER_SIZE)
nonceBuf = make([]byte, NONCE_SIZE)
toSend []byte
signingKey = peer.signPrivKey
reqPool = make(chan udpWriteReq, 1024)
writeChan = make(chan udpWriteReq, 1024)
)
for range cap(reqPool) {
reqPool <- udpWriteReq{Packet: make([]byte, BUFFER_SIZE)}
}
go udpWriter(writeChan, peer.conn, reqPool)
for {
n, err = iface.Read(packet[:BUFFER_SIZE])
if err != nil {
log.Fatalf("Failed to read from interface: %v", err)
}
if n < 20 {
log.Printf("Dropping small packet: %d", n)
continue
}
packet = packet[:n]
destIP = packet[19]
route = router.GetRoute(destIP)
if route == nil {
log.Printf("Dropping packet for non-existent IP: %d", destIP)
continue
}
now = uint64(fasttime.Now())
if counterTS < now {
counterTS = now
counter = now << 30
}
counter++
nonce.Counter = counter
nonce.ViaIP = route.ViaIP
nonce.DestIP = destIP
MarshalNonce(nonce, nonceBuf)
encrypted = encryptPacket(route.EncSharedKey, nonceBuf, packet, encrypted)
if route.ViaIP != 0 {
toSend = signPacket(signingKey, encrypted, packet)
} else {
toSend = encrypted
}
req := <-reqPool
req.Addr = route.Addr
req.Packet = req.Packet[:len(toSend)]
copy(req.Packet, toSend)
writeChan <- req
}
}
type udpWriteReq struct {
Addr netip.AddrPort
Packet []byte
}
func udpWriter(in chan udpWriteReq, conn *net.UDPConn, reqPool chan udpWriteReq) {
var err error
for req := range in {
if _, err = conn.WriteToUDPAddrPort(req.Packet, req.Addr); err != nil {
log.Fatalf("Failed to write UDP packet: %v", err)
}
reqPool <- req
}
}