package main /* Two-Nodes A simple demo for showcasing the go-DDDNS working in a two nodes environment */ import ( "errors" "flag" "log" "net/http" "os" "os/signal" "strconv" "syscall" "time" godddns "github.com/tobychui/go-DDDNS/godddns" ) var ( //Flags //Current node thisNodeUUID = flag.String("nid", "node1", "The UUID of this node") //Remote nodes remoteNodeAUUID = flag.String("rida", "node2", "The UUID of the remote node A") remoteNodeAIPAddr = flag.String("ripa", "127.0.0.1", "The remote node A current IP address") remoteNodeBUUID = flag.String("ridb", "node3", "The UUID of the remote node B") remoteNodeBIPAddr = flag.String("ripb", "127.0.0.1", "The remote node B current IP address") //The following flags assume both remote node A and B are hosted on the same port and with same connection endpoint connPath = flag.String("conn", "/conn", "The relative path for connection establishment") thisNodeRecvPort = flag.Int("np", 8080, "This node receive port") remoteNodeRecvPort = flag.Int("rp", 8080, "Remote nodes (A and B) receive port") //Paramter, which we hardcoded here for now syncInterval int64 = 10 serviceRouter *godddns.ServiceRouter ) //Dummy function which allow all login to pass through func ValidateCred(username string, password string) bool { return true } func cleanup(configFilename string) { //Save the router record to json file /* js, err := serviceRouter.ExportRouterToJSON() if err != nil { panic(err) } ioutil.WriteFile(configFilename, []byte(js), 0755) */ //Close the service router serviceRouter.Close() } func main() { //Set-ups flag.Parse() configFilename := *thisNodeUUID + "_config.json" c := make(chan os.Signal) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c cleanup(configFilename) os.Exit(1) }() //Step 1: we want to create a new service router based on the given information if fileExists(configFilename) { //Load service router from file s, err := godddns.NewRouterFromJSONFile(configFilename) if err != nil { log.Println("Failed to load service router from file: ") panic(err) } s.InjectAuthFunction(ValidateCred) serviceRouter = s log.Println("Service Router Config Loaded") } else { //Create a new service router serviceRouter = godddns.NewServiceRouter(godddns.RouterOptions{ DeviceUUID: *thisNodeUUID, AuthFunction: ValidateCred, SyncInterval: syncInterval, }) log.Println("Service Router Created") } //Optional: Enable verbal output on router serviceRouter.Options.Verbal = true //Step 2: Create HTTP listening endpoint for incoming connection requests and heartbeat go func() { http.HandleFunc("/conn", serviceRouter.HandleConnections) log.Println("HTTP Listening endpoint started on :" + strconv.Itoa(*thisNodeRecvPort)) http.ListenAndServe(":"+strconv.Itoa(*thisNodeRecvPort), nil) }() if !fileExists(configFilename) { //Step 3: we want to add the remote nodes to the list //Node A nodeA := serviceRouter.NewNode(godddns.NodeOptions{ NodeID: *remoteNodeAUUID, Port: *remoteNodeRecvPort, RESTInterface: *connPath, RequireHTTPS: false, }) serviceRouter.AddNode(nodeA) log.Println("Remote NodeA Added") //Node B nodeB := serviceRouter.NewNode(godddns.NodeOptions{ NodeID: *remoteNodeBUUID, Port: *remoteNodeRecvPort, RESTInterface: *connPath, RequireHTTPS: false, }) serviceRouter.AddNode(nodeB) log.Println("Remote NodeB Added") //Step 4: Start the connection to Node 1 (Replace username and password with real value here) retryCount := 0 retry := true for retry { if retryCount > 10 { log.Println("Connection to remote node " + nodeA.UUID + " failed. Skipping.") break } assignedSendingTOTP, err := nodeA.StartConnection(*remoteNodeAIPAddr, "username", "password") if err != nil { log.Println("Unable to establish connection to Node A. Retrying in 3 seconds", assignedSendingTOTP) retryCount++ time.Sleep(3 * time.Second) } else { log.Println("Remote Node A TOTP exchange done:", assignedSendingTOTP) retry = false } } //Start connection to Node 2 retryCount = 0 retry = true for retry { if retryCount > 10 { log.Println("Connection to remote node " + nodeB.UUID + " failed. Skipping.") break } assignedSendingTOTP, err := nodeB.StartConnection(*remoteNodeBIPAddr, "username", "password") if err != nil { log.Println("Unable to establish connection to Node B. Retrying in 3 seconds", assignedSendingTOTP) retryCount++ time.Sleep(3 * time.Second) } else { log.Println("Node B TOTP exchange done:", assignedSendingTOTP) retry = false } } } //Step 4: Start Heartbeat to the remote node(s) serviceRouter.StartHeartBeat() log.Println("Heartbeat schedule started") //Do a blocking loop select {} } func fileExists(filename string) bool { if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) { return false } return true }