183 lines
3.8 KiB
Go
183 lines
3.8 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)
|
|
}
|
|
|
|
connWriter := newConnWriter(conn)
|
|
ifWriter := newIFWriter(iface)
|
|
|
|
peers := remotePeers{}
|
|
|
|
for i := range peers {
|
|
peers[i] = newRemotePeer(conf, byte(i), ifWriter, connWriter, &peers)
|
|
}
|
|
|
|
go newHubPoller(netName, conf, peers).Run()
|
|
go readFromConn(conn, peers)
|
|
readFromIFace(iface, peers)
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func determinePort(confPort, portFromCommandLine uint16) uint16 {
|
|
if portFromCommandLine != 0 {
|
|
return portFromCommandLine
|
|
}
|
|
if confPort != 0 {
|
|
return confPort
|
|
}
|
|
return 456
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func readFromConn(conn *net.UDPConn, peers remotePeers) {
|
|
|
|
defer panicHandler()
|
|
|
|
var (
|
|
remoteAddr netip.AddrPort
|
|
n int
|
|
err error
|
|
buf = make([]byte, bufferSize)
|
|
data []byte
|
|
h header
|
|
)
|
|
|
|
for {
|
|
n, remoteAddr, err = conn.ReadFromUDPAddrPort(buf[:bufferSize])
|
|
if err != nil {
|
|
log.Fatalf("Failed to read from UDP port: %v", err)
|
|
}
|
|
|
|
data = buf[:n]
|
|
|
|
if n < headerSize {
|
|
continue // Packet it soo short.
|
|
}
|
|
|
|
h.Parse(data)
|
|
peers[h.SourceIP].HandlePacket(remoteAddr, h, data)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func readFromIFace(iface io.ReadWriteCloser, peers remotePeers) {
|
|
|
|
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)
|
|
}
|
|
|
|
peers[remoteIP].HandleInterfacePacket(packet)
|
|
}
|
|
}
|