main.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package main
  2. /*
  3. Two-Nodes
  4. A simple demo for showcasing the go-DDDNS working in a two nodes environment
  5. */
  6. import (
  7. "errors"
  8. "flag"
  9. "log"
  10. "net/http"
  11. "os"
  12. "os/signal"
  13. "strconv"
  14. "syscall"
  15. "time"
  16. godddns "github.com/tobychui/go-DDDNS/godddns"
  17. )
  18. var (
  19. //Flags
  20. //Current node
  21. thisNodeUUID = flag.String("nid", "node1", "The UUID of this node")
  22. //Remote nodes
  23. remoteNodeAUUID = flag.String("rida", "node2", "The UUID of the remote node A")
  24. remoteNodeAIPAddr = flag.String("ripa", "127.0.0.1", "The remote node A current IP address")
  25. remoteNodeBUUID = flag.String("ridb", "node3", "The UUID of the remote node B")
  26. remoteNodeBIPAddr = flag.String("ripb", "127.0.0.1", "The remote node B current IP address")
  27. //The following flags assume both remote node A and B are hosted on the same port and with same connection endpoint
  28. connPath = flag.String("conn", "/conn", "The relative path for connection establishment")
  29. thisNodeRecvPort = flag.Int("np", 8080, "This node receive port")
  30. remoteNodeRecvPort = flag.Int("rp", 8080, "Remote nodes (A and B) receive port")
  31. //Paramter, which we hardcoded here for now
  32. syncInterval int64 = 10
  33. serviceRouter *godddns.ServiceRouter
  34. )
  35. //Dummy function which allow all login to pass through
  36. func ValidateCred(username string, password string) bool {
  37. return true
  38. }
  39. func cleanup(configFilename string) {
  40. //Save the router record to json file
  41. /*
  42. js, err := serviceRouter.ExportRouterToJSON()
  43. if err != nil {
  44. panic(err)
  45. }
  46. ioutil.WriteFile(configFilename, []byte(js), 0755)
  47. */
  48. //Close the service router
  49. serviceRouter.Close()
  50. }
  51. func main() {
  52. //Set-ups
  53. flag.Parse()
  54. configFilename := *thisNodeUUID + "_config.json"
  55. c := make(chan os.Signal)
  56. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  57. go func() {
  58. <-c
  59. cleanup(configFilename)
  60. os.Exit(1)
  61. }()
  62. //Step 1: we want to create a new service router based on the given information
  63. if fileExists(configFilename) {
  64. //Load service router from file
  65. s, err := godddns.NewRouterFromJSONFile(configFilename)
  66. if err != nil {
  67. log.Println("Failed to load service router from file: ")
  68. panic(err)
  69. }
  70. s.InjectAuthFunction(ValidateCred)
  71. serviceRouter = s
  72. log.Println("Service Router Config Loaded")
  73. } else {
  74. //Create a new service router
  75. serviceRouter = godddns.NewServiceRouter(godddns.RouterOptions{
  76. DeviceUUID: *thisNodeUUID,
  77. AuthFunction: ValidateCred,
  78. SyncInterval: syncInterval,
  79. })
  80. log.Println("Service Router Created")
  81. }
  82. //Optional: Enable verbal output on router
  83. serviceRouter.Options.Verbal = true
  84. //Step 2: Create HTTP listening endpoint for incoming connection requests and heartbeat
  85. go func() {
  86. http.HandleFunc("/conn", serviceRouter.HandleConnections)
  87. log.Println("HTTP Listening endpoint started on :" + strconv.Itoa(*thisNodeRecvPort))
  88. http.ListenAndServe(":"+strconv.Itoa(*thisNodeRecvPort), nil)
  89. }()
  90. if !fileExists(configFilename) {
  91. //Step 3: we want to add the remote nodes to the list
  92. //Node A
  93. nodeA := serviceRouter.NewNode(godddns.NodeOptions{
  94. NodeID: *remoteNodeAUUID,
  95. Port: *remoteNodeRecvPort,
  96. RESTInterface: *connPath,
  97. RequireHTTPS: false,
  98. })
  99. serviceRouter.AddNode(nodeA)
  100. log.Println("Remote NodeA Added")
  101. //Node B
  102. nodeB := serviceRouter.NewNode(godddns.NodeOptions{
  103. NodeID: *remoteNodeBUUID,
  104. Port: *remoteNodeRecvPort,
  105. RESTInterface: *connPath,
  106. RequireHTTPS: false,
  107. })
  108. serviceRouter.AddNode(nodeB)
  109. log.Println("Remote NodeB Added")
  110. //Step 4: Start the connection to Node 1 (Replace username and password with real value here)
  111. retryCount := 0
  112. retry := true
  113. for retry {
  114. if retryCount > 10 {
  115. log.Println("Connection to remote node " + nodeA.UUID + " failed. Skipping.")
  116. break
  117. }
  118. assignedSendingTOTP, err := nodeA.StartConnection(*remoteNodeAIPAddr, "username", "password")
  119. if err != nil {
  120. log.Println("Unable to establish connection to Node A. Retrying in 3 seconds", assignedSendingTOTP)
  121. retryCount++
  122. time.Sleep(3 * time.Second)
  123. } else {
  124. log.Println("Remote Node A TOTP exchange done:", assignedSendingTOTP)
  125. retry = false
  126. }
  127. }
  128. //Start connection to Node 2
  129. retryCount = 0
  130. retry = true
  131. for retry {
  132. if retryCount > 10 {
  133. log.Println("Connection to remote node " + nodeB.UUID + " failed. Skipping.")
  134. break
  135. }
  136. assignedSendingTOTP, err := nodeB.StartConnection(*remoteNodeBIPAddr, "username", "password")
  137. if err != nil {
  138. log.Println("Unable to establish connection to Node B. Retrying in 3 seconds", assignedSendingTOTP)
  139. retryCount++
  140. time.Sleep(3 * time.Second)
  141. } else {
  142. log.Println("Node B TOTP exchange done:", assignedSendingTOTP)
  143. retry = false
  144. }
  145. }
  146. }
  147. //Step 4: Start Heartbeat to the remote node(s)
  148. serviceRouter.StartHeartBeat()
  149. log.Println("Heartbeat schedule started")
  150. //Do a blocking loop
  151. select {}
  152. }
  153. func fileExists(filename string) bool {
  154. if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
  155. return false
  156. }
  157. return true
  158. }