123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- 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
- }
|