vppn/node/main.go
2024-12-18 12:35:47 +01:00

191 lines
4.1 KiB
Go

package node
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"net/netip"
"os"
"runtime/debug"
"vppn/m"
)
func panicHandler() {
if r := recover(); r != nil {
log.Fatalf("\n %v\n\nstacktrace from panic: %s\n", r, string(debug.Stack()))
}
}
func Main() {
defer panicHandler()
var (
netName string
initURL string
listenIP string
port int
)
flag.StringVar(&netName, "name", "", "[REQUIRED] The network name.")
flag.StringVar(&initURL, "init-url", "", "Initializes peer from the hub URL.")
flag.StringVar(&listenIP, "listen-ip", "", "IP address to listen on.")
flag.IntVar(&port, "port", 0, "Port to listen on.")
flag.Parse()
if netName == "" {
flag.Usage()
os.Exit(1)
}
if initURL != "" {
mainInit(netName, initURL)
return
}
main(netName, listenIP, uint16(port))
}
func mainInit(netName, initURL string) {
if _, err := loadPeerConfig(netName); err == nil {
log.Fatalf("Network is already initialized.")
}
resp, err := http.Get(initURL)
if err != nil {
log.Fatalf("Failed to fetch data from hub: %v", err)
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Failed to read response body: %v", err)
}
peerConfig := m.PeerConfig{}
if err := json.Unmarshal(data, &peerConfig); err != nil {
log.Fatalf("Failed to parse configuration: %v", err)
}
if err := storePeerConfig(netName, peerConfig); err != nil {
log.Fatalf("Failed to store configuration: %v", err)
}
log.Print("Initialization successful.")
}
// ----------------------------------------------------------------------------
func main(netName, listenIP string, port uint16) {
conf, err := loadPeerConfig(netName)
if err != nil {
log.Fatalf("Failed to load configuration: %v", err)
}
port = determinePort(conf.Port, port)
iface, err := openInterface(conf.Network, conf.PeerIP, netName)
if err != nil {
log.Fatalf("Failed to open interface: %v", err)
}
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", listenIP, port))
if err != nil {
log.Fatalf("Failed to resolve UDP address: %v", err)
}
conn, err := net.ListenUDP("udp", myAddr)
if err != nil {
log.Fatalf("Failed to open UDP port: %v", err)
}
routing := newRoutingTable()
w := newConnWriter(conn, conf.PeerIP, routing)
r := newConnReader(conn, conf.PeerIP, routing)
router := newRouter(netName, conf, routing, w)
go nodeConnReader(r, w, iface, router)
nodeIFaceReader(w, iface, router)
}
// ----------------------------------------------------------------------------
func determinePort(confPort, portFromCommandLine uint16) uint16 {
if portFromCommandLine != 0 {
return portFromCommandLine
}
if confPort != 0 {
return confPort
}
return 456
}
// ----------------------------------------------------------------------------
func nodeConnReader(r *connReader, w *connWriter, iface io.ReadWriteCloser, router *router) {
defer panicHandler()
var (
remoteAddr netip.AddrPort
h header
buf = make([]byte, bufferSize)
data []byte
err error
)
for {
remoteAddr, h, data, err = r.Read(buf)
if err != nil {
log.Fatalf("Failed to read from UDP connection: %v", err)
}
switch h.Stream {
case streamData:
if _, err = iface.Write(data); err != nil {
log.Printf("Malformed data from peer %d: %v", h.SourceIP, err)
}
case streamRouting:
router.HandlePacket(h.SourceIP, remoteAddr, data)
default:
log.Printf("Dropping unknown stream: %d", h.Stream)
}
}
}
// ----------------------------------------------------------------------------
func nodeIFaceReader(w *connWriter, iface io.ReadWriteCloser, router *router) {
var (
buf = make([]byte, bufferSize)
packet []byte
remoteIP byte
err error
)
for {
packet, remoteIP, err = readNextPacket(iface, buf)
if err != nil {
log.Fatalf("Failed to read from interface: %v", err)
}
if remoteIP == w.localIP {
//log.Printf("Incoming packet for self: %x", packet)
//iface.Write(packet)
continue
}
if err := w.WriteTo(remoteIP, streamData, packet); err != nil {
log.Fatalf("Failed to write to network: %v", err)
}
}
}