65 lines
1.4 KiB
Go
65 lines
1.4 KiB
Go
package peer
|
|
|
|
import (
|
|
"log"
|
|
"net"
|
|
"net/netip"
|
|
|
|
"vppn/peer/control"
|
|
)
|
|
|
|
var _ ControlConn = (*udpControlConn)(nil)
|
|
|
|
type udpControlConn struct {
|
|
conn *net.UDPConn
|
|
}
|
|
|
|
// newUDPControlConn opens a UDP socket bound to localIP:port.
|
|
func newUDPControlConn(localIP netip.Addr, port uint16) (*udpControlConn, error) {
|
|
addr := net.UDPAddrFromAddrPort(netip.AddrPortFrom(localIP, port))
|
|
conn, err := net.ListenUDP("udp4", addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &udpControlConn{conn: conn}, nil
|
|
}
|
|
|
|
func (c *udpControlConn) SendPing(dst netip.AddrPort, ping control.Ping, buf []byte) error {
|
|
_, err := c.conn.WriteToUDP(ping.Marshal(buf), net.UDPAddrFromAddrPort(dst))
|
|
return err
|
|
}
|
|
|
|
// run reads incoming ping packets and forwards them to ch until ctx is done.
|
|
// Call this in a goroutine before starting the App event loop.
|
|
func (c *udpControlConn) run(ch chan<- PingEvent) {
|
|
var buf [control.Size]byte
|
|
for {
|
|
n, src, err := c.conn.ReadFromUDP(buf[:])
|
|
if err != nil {
|
|
log.Printf("control read: %v", err)
|
|
continue
|
|
}
|
|
|
|
if n != control.Size {
|
|
continue
|
|
}
|
|
|
|
ping, err := control.Unmarshal(buf)
|
|
if err != nil {
|
|
log.Printf("control unmarshal: %v", err)
|
|
continue
|
|
}
|
|
|
|
srcIP, ok := netip.AddrFromSlice(src.IP)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
ch <- PingEvent{srcVPNIP: srcIP.Unmap(), ping: ping}
|
|
}
|
|
}
|
|
|
|
func (c *udpControlConn) Close() error {
|
|
return c.conn.Close()
|
|
}
|