vppn/peer/connwriter.go
2025-02-10 19:11:30 +01:00

81 lines
2.3 KiB
Go

package peer
import (
"log"
"net/netip"
"sync"
)
// ----------------------------------------------------------------------------
type connWriter struct {
localIP byte
conn udpWriter
// For sending control packets.
cBuf1 []byte
cBuf2 []byte
// For sending data packets.
dBuf1 []byte
dBuf2 []byte
// Lock around for sending on UDP Conn.
wLock sync.Mutex
}
func newConnWriter(conn udpWriter, localIP byte) *connWriter {
w := &connWriter{
localIP: localIP,
conn: conn,
cBuf1: make([]byte, bufferSize),
cBuf2: make([]byte, bufferSize),
dBuf1: make([]byte, bufferSize),
dBuf2: make([]byte, bufferSize),
}
return w
}
// Not safe for concurrent use. Should only be called by supervisor.
func (w *connWriter) SendControlPacket(pkt Marshaller, peer *RemotePeer) {
enc := encryptControlPacket(w.localIP, peer, pkt, w.cBuf1, w.cBuf2)
w.writeTo(enc, peer.DirectAddr)
}
// Relay control packet. Peer must not be nil.
func (w *connWriter) RelayControlPacket(pkt Marshaller, peer, relay *RemotePeer) {
enc := encryptControlPacket(w.localIP, peer, pkt, w.cBuf1, w.cBuf2)
enc = encryptDataPacket(w.localIP, peer.IP, relay, enc, w.cBuf1)
w.writeTo(enc, relay.DirectAddr)
}
// Not safe for concurrent use. Should only be called by ifReader.
func (w *connWriter) SendDataPacket(pkt []byte, peer *RemotePeer) {
enc := encryptDataPacket(w.localIP, peer.IP, peer, pkt, w.dBuf1)
w.writeTo(enc, peer.DirectAddr)
}
// Relay a data packet. Peer must not be nil.
func (w *connWriter) RelayDataPacket(pkt []byte, peer, relay *RemotePeer) {
enc := encryptDataPacket(w.localIP, peer.IP, peer, pkt, w.dBuf1)
enc = encryptDataPacket(w.localIP, peer.IP, relay, enc, w.dBuf2)
w.writeTo(enc, relay.DirectAddr)
}
// Safe for concurrent use. Should only be called by connReader.
//
// This function will send pkt to the peer directly. This is used when a peer
// is acting as a relay and is forwarding already encrypted data for another
// peer.
func (w *connWriter) SendEncryptedDataPacket(pkt []byte, peer *RemotePeer) {
w.writeTo(pkt, peer.DirectAddr)
}
func (w *connWriter) writeTo(packet []byte, addr netip.AddrPort) {
w.wLock.Lock()
if _, err := w.conn.WriteToUDPAddrPort(packet, addr); err != nil {
log.Printf("[ConnWriter] Failed to write to UDP port: %v", err)
}
w.wLock.Unlock()
}