Browse Source

api to to get host relayed from client

Abhishek Kondur 1 year ago
parent
commit
cb4d860ca6
3 changed files with 90 additions and 1 deletions
  1. 4 0
      models/host.go
  2. 64 1
      pro/controllers/relay.go
  3. 22 0
      pro/logic/relays.go

+ 4 - 0
models/host.go

@@ -70,6 +70,7 @@ type Host struct {
 	NatType             string           `json:"nat_type,omitempty"      yaml:"nat_type,omitempty"`
 	TurnEndpoint        *netip.AddrPort  `json:"turn_endpoint,omitempty" yaml:"turn_endpoint,omitempty"`
 	PersistentKeepalive time.Duration    `json:"persistentkeepalive"     yaml:"persistentkeepalive"`
+	AutoRelay           bool             `json:"auto_relay" yaml:"auto_relay"`
 }
 
 // FormatBool converts a boolean to a [yes|no] string
@@ -126,6 +127,8 @@ const (
 	Disconnect SignalAction = "DISCONNECT"
 	// ConnNegotiation - action to negotiate connection between peers
 	ConnNegotiation SignalAction = "CONNECTION_NEGOTIATION"
+	// RelayME - action to relay the peer
+	RelayME SignalAction = "RELAY_ME"
 )
 
 // HostUpdate - struct for host update
@@ -150,6 +153,7 @@ type Signal struct {
 	ToHostPubKey      string       `json:"to_host_pubkey"`
 	Reply             bool         `json:"reply"`
 	Action            SignalAction `json:"action"`
+	IsPro             bool         `json:"is_pro"`
 	TimeStamp         int64        `json:"timestamp"`
 }
 

+ 64 - 1
pro/controllers/relay.go

@@ -3,9 +3,11 @@ package controllers
 import (
 	"encoding/json"
 	"fmt"
-	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"net/http"
 
+	proLogic "github.com/gravitl/netmaker/pro/logic"
+	"golang.org/x/exp/slog"
+
 	"github.com/gorilla/mux"
 	controller "github.com/gravitl/netmaker/controllers"
 	"github.com/gravitl/netmaker/logger"
@@ -19,6 +21,7 @@ func RelayHandlers(r *mux.Router) {
 
 	r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", controller.Authorize(false, true, "user", http.HandlerFunc(createRelay))).Methods(http.MethodPost)
 	r.HandleFunc("/api/nodes/{network}/{nodeid}/deleterelay", controller.Authorize(false, true, "user", http.HandlerFunc(deleteRelay))).Methods(http.MethodDelete)
+	r.HandleFunc("/api/host/{hostid}/relayme", controller.Authorize(true, true, "host", http.HandlerFunc(relayme))).Methods(http.MethodPost)
 }
 
 // swagger:route POST /api/nodes/{network}/{nodeid}/createrelay nodes createRelay
@@ -109,3 +112,63 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(apiNode)
 }
+
+// swagger:route POST /api/host/relayme host relayme
+//
+// Create a relay.
+//
+//			Schemes: https
+//
+//			Security:
+//	  		oauth
+//
+//			Responses:
+//				200: nodeResponse
+func relayme(w http.ResponseWriter, r *http.Request) {
+	var params = mux.Vars(r)
+	hostid := params["hostid"]
+	// confirm host exists
+	host, err := logic.GetHost(hostid)
+	if err != nil {
+		logger.Log(0, r.Header.Get("user"), "failed to get host:", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+		return
+	}
+	var sendPeerUpdate bool
+	for _, nodeID := range host.Nodes {
+		node, err := logic.GetNodeByID(nodeID)
+		if err != nil {
+			slog.Error("couldn't find node", "id", nodeID, "error", err)
+			continue
+		}
+		if node.IsRelayed {
+			continue
+		}
+		// get auto relay Host in this network
+		relayNode, err := proLogic.GetAutoRelayHostNode(node.Network)
+		if err != nil {
+			slog.Error("auto relay not found", "network", node.Network)
+			continue
+		}
+		relayNode.RelayedNodes = append(relayNode.RelayedNodes, node.ID.String())
+		_, _, err = proLogic.CreateRelay(models.RelayRequest{
+			NodeID:       relayNode.ID.String(),
+			NetID:        node.Network,
+			RelayedNodes: relayNode.RelayedNodes,
+		})
+		if err != nil {
+			slog.Error("failed to create relay:", "id", node.ID.String(),
+				"network", node.Network, "error", err)
+			continue
+		}
+		slog.Info("[auto-relay] created relay on node", "node", node.ID.String(), "network", node.Network)
+		sendPeerUpdate = true
+	}
+
+	if sendPeerUpdate {
+		go mq.PublishPeerUpdate()
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	w.WriteHeader(http.StatusOK)
+}

+ 22 - 0
pro/logic/relays.go

@@ -240,3 +240,25 @@ func getRelayedAddresses(id string) []net.IPNet {
 	}
 	return addrs
 }
+
+// GetAutoRelayHostNode - gets the host acting as auto relay in the network
+func GetAutoRelayHostNode(network string) (models.Node, error) {
+	hosts, err := logic.GetAllHosts()
+	if err != nil {
+		return models.Node{}, err
+	}
+	for _, host := range hosts {
+		if host.AutoRelay {
+			for _, nodeid := range host.Nodes {
+				node, err := logic.GetNodeByID(nodeid)
+				if err != nil {
+					continue
+				}
+				if node.Network == network {
+					return node, nil
+				}
+			}
+		}
+	}
+	return models.Node{}, errors.New("auto relay not found")
+}