mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-01 01:35:06 +03:00 
			
		
		
		
	Refactor admin socket, export request/response structs, remove types package
This commit is contained in:
		
							parent
							
								
									dfca87ba80
								
							
						
					
					
						commit
						2d01386d6e
					
				
					 13 changed files with 290 additions and 218 deletions
				
			
		|  | @ -1,7 +1,6 @@ | |||
| package admin | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | @ -9,17 +8,12 @@ import ( | |||
| 	"net/url" | ||||
| 	"os" | ||||
| 
 | ||||
| 	//"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gologme/log" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/config" | ||||
| 	//"github.com/yggdrasil-network/yggdrasil-go/src/crypto" | ||||
| 	//"github.com/yggdrasil-network/yggdrasil-go/src/util" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/version" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" | ||||
| ) | ||||
| 
 | ||||
|  | @ -34,16 +28,26 @@ type AdminSocket struct { | |||
| 	started    bool | ||||
| } | ||||
| 
 | ||||
| // Info refers to information that is returned to the admin socket handler. | ||||
| type Info map[string]interface{} | ||||
| type AdminSocketResponse struct { | ||||
| 	Status  string `json:"status"` | ||||
| 	Request struct { | ||||
| 		Name      string `json:"request"` | ||||
| 		KeepAlive bool   `json:"keepalive"` | ||||
| 	} `json:"request"` | ||||
| 	Response interface{} `json:"response"` | ||||
| } | ||||
| 
 | ||||
| type handler struct { | ||||
| 	args    []string                                   // List of human-readable argument names | ||||
| 	handler func(Info) (Info, error) // First is input map, second is output | ||||
| 	handler func(json.RawMessage) (interface{}, error) // First is input map, second is output | ||||
| } | ||||
| 
 | ||||
| type ListResponse struct { | ||||
| 	List map[string][]string `json:"list"` | ||||
| } | ||||
| 
 | ||||
| // AddHandler is called for each admin function to add the handler and help documentation to the API. | ||||
| func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(Info) (Info, error)) error { | ||||
| func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(json.RawMessage) (interface{}, error)) error { | ||||
| 	if _, ok := a.handlers[strings.ToLower(name)]; ok { | ||||
| 		return errors.New("handler already exists") | ||||
| 	} | ||||
|  | @ -61,70 +65,60 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log. | |||
| 	a.handlers = make(map[string]handler) | ||||
| 	current := state.GetCurrent() | ||||
| 	a.listenaddr = current.AdminListen | ||||
| 	a.AddHandler("list", []string{}, func(in Info) (Info, error) { | ||||
| 		handlers := make(map[string]interface{}) | ||||
| 		for handlername, handler := range a.handlers { | ||||
| 			handlers[handlername] = Info{"fields": handler.args} | ||||
| 	_ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) { | ||||
| 		res := &ListResponse{} | ||||
| 		for name, handler := range a.handlers { | ||||
| 			res.List[name] = handler.args | ||||
| 		} | ||||
| 		return Info{"list": handlers}, nil | ||||
| 		return res, nil | ||||
| 	}) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) { | ||||
| 	a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) { | ||||
| 		ip := a.core.Address().String() | ||||
| 		subnet := a.core.Subnet() | ||||
| 		self := a.core.GetSelf() | ||||
| 		return Info{ | ||||
| 			"self": Info{ | ||||
| 				ip: Info{ | ||||
| 					// TODO"box_pub_key":   a.core.EncryptionPublicKey(), | ||||
| 					"build_name":    version.BuildName(), | ||||
| 					"build_version": version.BuildVersion(), | ||||
| 					"key":           hex.EncodeToString(self.Key[:]), | ||||
| 					"coords":        fmt.Sprintf("%v", self.Coords), | ||||
| 					"subnet":        subnet.String(), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, nil | ||||
| 	_ = a.AddHandler("getSelf", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetSelfRequest{} | ||||
| 		res := &GetSelfResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if err := a.getSelfHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return res, nil | ||||
| 	}) | ||||
| 	a.AddHandler("getPeers", []string{}, func(in Info) (Info, error) { | ||||
| 		peers := make(Info) | ||||
| 		for _, p := range a.core.GetPeers() { | ||||
| 			addr := address.AddrForKey(p.Key) | ||||
| 			so := net.IP(addr[:]).String() | ||||
| 			peers[so] = Info{ | ||||
| 				"key":    hex.EncodeToString(p.Key[:]), | ||||
| 				"port":   p.Port, | ||||
| 				"coords": fmt.Sprintf("%v", p.Coords), | ||||
| 	_ = a.AddHandler("getPeers", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetPeersRequest{} | ||||
| 		res := &GetPeersResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if err := a.getPeersHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return Info{"peers": peers}, nil | ||||
| 		return res, nil | ||||
| 	}) | ||||
| 	a.AddHandler("getDHT", []string{}, func(in Info) (Info, error) { | ||||
| 		dht := make(Info) | ||||
| 		for _, d := range a.core.GetDHT() { | ||||
| 			addr := address.AddrForKey(d.Key) | ||||
| 			so := net.IP(addr[:]).String() | ||||
| 			dht[so] = Info{ | ||||
| 				"key":  hex.EncodeToString(d.Key[:]), | ||||
| 				"port": fmt.Sprintf("%v", d.Port), | ||||
| 				"next": fmt.Sprintf("%v", d.Next), | ||||
| 	_ = a.AddHandler("getDHT", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetDHTRequest{} | ||||
| 		res := &GetDHTResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if err := a.getDHTHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return Info{"dht": dht}, nil | ||||
| 		return res, nil | ||||
| 	}) | ||||
| 	a.AddHandler("getSessions", []string{}, func(in Info) (Info, error) { | ||||
| 		sessions := make(Info) | ||||
| 		for _, s := range a.core.GetSessions() { | ||||
| 			addr := address.AddrForKey(s.Key) | ||||
| 			so := net.IP(addr[:]).String() | ||||
| 			sessions[so] = Info{ | ||||
| 				"key": hex.EncodeToString(s.Key[:]), | ||||
| 	_ = a.AddHandler("getSessions", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetSessionsRequest{} | ||||
| 		res := &GetSessionsResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if err := a.getSessionsHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return Info{"sessions": sessions}, nil | ||||
| 		return res, nil | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
|  | @ -209,20 +203,20 @@ func (a *AdminSocket) listen() { | |||
| // handleRequest calls the request handler for each request sent to the admin API. | ||||
| func (a *AdminSocket) handleRequest(conn net.Conn) { | ||||
| 	decoder := json.NewDecoder(conn) | ||||
| 	decoder.DisallowUnknownFields() | ||||
| 
 | ||||
| 	encoder := json.NewEncoder(conn) | ||||
| 	encoder.SetIndent("", "  ") | ||||
| 	recv := make(Info) | ||||
| 	send := make(Info) | ||||
| 
 | ||||
| 	defer conn.Close() | ||||
| 
 | ||||
| 	defer func() { | ||||
| 		r := recover() | ||||
| 		if r != nil { | ||||
| 			send = Info{ | ||||
| 				"status": "error", | ||||
| 				"error":  "Check your syntax and input types", | ||||
| 			} | ||||
| 			a.log.Debugln("Admin socket error:", r) | ||||
| 			if err := encoder.Encode(&send); err != nil { | ||||
| 			if err := encoder.Encode(&ErrorResponse{ | ||||
| 				Error: "Check your syntax and input types", | ||||
| 			}); err != nil { | ||||
| 				a.log.Debugln("Admin socket JSON encode error:", err) | ||||
| 			} | ||||
| 			conn.Close() | ||||
|  | @ -230,83 +224,40 @@ func (a *AdminSocket) handleRequest(conn net.Conn) { | |||
| 	}() | ||||
| 
 | ||||
| 	for { | ||||
| 		// Start with a clean slate on each request | ||||
| 		recv = Info{} | ||||
| 		send = Info{} | ||||
| 
 | ||||
| 		// Decode the input | ||||
| 		if err := decoder.Decode(&recv); err != nil { | ||||
| 			a.log.Debugln("Admin socket JSON decode error:", err) | ||||
| 			return | ||||
| 		var err error | ||||
| 		var buf json.RawMessage | ||||
| 		_ = decoder.Decode(&buf) | ||||
| 		var resp AdminSocketResponse | ||||
| 		resp.Status = "success" | ||||
| 		if err = json.Unmarshal(buf, &resp.Request); err == nil { | ||||
| 			if resp.Request.Name == "" { | ||||
| 				resp.Status = "error" | ||||
| 				resp.Response = &ErrorResponse{ | ||||
| 					Error: "No request specified", | ||||
| 				} | ||||
| 
 | ||||
| 		// Send the request back with the response, and default to "error" | ||||
| 		// unless the status is changed below by one of the handlers | ||||
| 		send["request"] = recv | ||||
| 		send["status"] = "error" | ||||
| 
 | ||||
| 		n := strings.ToLower(recv["request"].(string)) | ||||
| 
 | ||||
| 		if _, ok := recv["request"]; !ok { | ||||
| 			send["error"] = "No request sent" | ||||
| 			goto respond | ||||
| 		} | ||||
| 
 | ||||
| 		if h, ok := a.handlers[n]; ok { | ||||
| 			// Check that we have all the required arguments | ||||
| 			for _, arg := range h.args { | ||||
| 				// An argument in [square brackets] is optional and not required, | ||||
| 				// so we can safely ignore those | ||||
| 				if strings.HasPrefix(arg, "[") && strings.HasSuffix(arg, "]") { | ||||
| 					continue | ||||
| 				} | ||||
| 				// Check if the field is missing | ||||
| 				if _, ok := recv[arg]; !ok { | ||||
| 					send = Info{ | ||||
| 						"status":    "error", | ||||
| 						"error":     "Expected field missing: " + arg, | ||||
| 						"expecting": arg, | ||||
| 					} | ||||
| 					goto respond | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// By this point we should have all the fields we need, so call | ||||
| 			// the handler | ||||
| 			response, err := h.handler(recv) | ||||
| 			} else if h, ok := a.handlers[strings.ToLower(resp.Request.Name)]; ok { | ||||
| 				resp.Response, err = h.handler(buf) | ||||
| 				if err != nil { | ||||
| 				send["error"] = err.Error() | ||||
| 				if response != nil { | ||||
| 					send["response"] = response | ||||
| 					goto respond | ||||
| 				} | ||||
| 			} else { | ||||
| 				send["status"] = "success" | ||||
| 				if response != nil { | ||||
| 					send["response"] = response | ||||
| 					goto respond | ||||
| 					resp.Status = "error" | ||||
| 					resp.Response = &ErrorResponse{ | ||||
| 						Error: err.Error(), | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 			// Start with a clean response on each request, which defaults to an error | ||||
| 			// state. If a handler is found below then this will be overwritten | ||||
| 			send = Info{ | ||||
| 				"request": recv, | ||||
| 				"status":  "error", | ||||
| 				"error":   fmt.Sprintf("Unknown action '%s', try 'list' for help", recv["request"].(string)), | ||||
| 				resp.Status = "error" | ||||
| 				resp.Response = &ErrorResponse{ | ||||
| 					Error: fmt.Sprintf("Unknown action '%s', try 'list' for help", resp.Request.Name), | ||||
| 				} | ||||
| 			goto respond | ||||
| 			} | ||||
| 
 | ||||
| 		// Send the response back | ||||
| 	respond: | ||||
| 		if err := encoder.Encode(&send); err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// If "keepalive" isn't true then close the connection | ||||
| 		if keepalive, ok := recv["keepalive"]; !ok || !keepalive.(bool) { | ||||
| 			conn.Close() | ||||
| 		j, _ := json.Marshal(resp) | ||||
| 		if err = encoder.Encode(resp); err != nil { | ||||
| 			a.log.Debugln("Encode error:", err) | ||||
| 		} | ||||
| 		if !resp.Request.KeepAlive { | ||||
| 			break | ||||
| 		} else { | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										5
									
								
								src/admin/error.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/admin/error.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| package admin | ||||
| 
 | ||||
| type ErrorResponse struct { | ||||
| 	Error string `json:"error"` | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/admin/getdht.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/admin/getdht.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| package admin | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| ) | ||||
| 
 | ||||
| type GetDHTRequest struct{} | ||||
| 
 | ||||
| type GetDHTResponse struct { | ||||
| 	DHT map[string]DHTEntry `json:"dht"` | ||||
| } | ||||
| 
 | ||||
| type DHTEntry struct { | ||||
| 	PublicKey string `json:"key"` | ||||
| 	Port      uint64 `json:"port"` | ||||
| 	Next      uint64 `json:"next"` | ||||
| } | ||||
| 
 | ||||
| func (a *AdminSocket) getDHTHandler(req *GetDHTRequest, res *GetDHTResponse) error { | ||||
| 	res.DHT = map[string]DHTEntry{} | ||||
| 	for _, d := range a.core.GetDHT() { | ||||
| 		addr := address.AddrForKey(d.Key) | ||||
| 		so := net.IP(addr[:]).String() | ||||
| 		res.DHT[so] = DHTEntry{ | ||||
| 			PublicKey: hex.EncodeToString(d.Key[:]), | ||||
| 			Port:      d.Port, | ||||
| 			Next:      d.Next, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										35
									
								
								src/admin/getpeers.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/admin/getpeers.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| package admin | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| ) | ||||
| 
 | ||||
| type GetPeersRequest struct { | ||||
| } | ||||
| 
 | ||||
| type GetPeersResponse struct { | ||||
| 	Peers map[string]PeerEntry `json:"peers"` | ||||
| } | ||||
| 
 | ||||
| type PeerEntry struct { | ||||
| 	PublicKey string   `json:"key"` | ||||
| 	Port      uint64   `json:"port"` | ||||
| 	Coords    []uint64 `json:"coords"` | ||||
| } | ||||
| 
 | ||||
| func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error { | ||||
| 	res.Peers = map[string]PeerEntry{} | ||||
| 	for _, p := range a.core.GetPeers() { | ||||
| 		addr := address.AddrForKey(p.Key) | ||||
| 		so := net.IP(addr[:]).String() | ||||
| 		res.Peers[so] = PeerEntry{ | ||||
| 			PublicKey: hex.EncodeToString(p.Key), | ||||
| 			Port:      p.Port, | ||||
| 			Coords:    p.Coords, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/admin/getself.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/admin/getself.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| package admin | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/ed25519" | ||||
| 	"encoding/hex" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/version" | ||||
| ) | ||||
| 
 | ||||
| type GetSelfRequest struct{} | ||||
| 
 | ||||
| type GetSelfResponse struct { | ||||
| 	BuildName    string   `json:"build_name"` | ||||
| 	BuildVersion string   `json:"build_version"` | ||||
| 	PublicKey    string   `json:"key"` | ||||
| 	Coords       []uint64 `json:"coords"` | ||||
| 	IPAddress    string   `json:"address"` | ||||
| 	Subnet       string   `json:"subnet"` | ||||
| } | ||||
| 
 | ||||
| func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error { | ||||
| 	res.BuildName = version.BuildName() | ||||
| 	res.BuildVersion = version.BuildVersion() | ||||
| 	public := a.core.PrivateKey().Public().(ed25519.PublicKey) | ||||
| 	res.PublicKey = hex.EncodeToString(public[:]) | ||||
| 	res.IPAddress = a.core.Address().String() | ||||
| 	snet := a.core.Subnet() | ||||
| 	res.Subnet = snet.String() | ||||
| 	// TODO: res.coords | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/admin/getsessions.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/admin/getsessions.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| package admin | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| ) | ||||
| 
 | ||||
| type GetSessionsRequest struct{} | ||||
| 
 | ||||
| type GetSessionsResponse struct { | ||||
| 	Sessions map[string]SessionEntry `json:"sessions"` | ||||
| } | ||||
| 
 | ||||
| type SessionEntry struct { | ||||
| 	PublicKey string `json:"key"` | ||||
| } | ||||
| 
 | ||||
| func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error { | ||||
| 	res.Sessions = map[string]SessionEntry{} | ||||
| 	for _, s := range a.core.GetSessions() { | ||||
| 		addr := address.AddrForKey(s.Key) | ||||
| 		so := net.IP(addr[:]).String() | ||||
| 		res.Sessions[so] = SessionEntry{ | ||||
| 			PublicKey: hex.EncodeToString(s.Key[:]), | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -22,11 +22,8 @@ import ( | |||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/crypto" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/defaults" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/types" | ||||
| ) | ||||
| 
 | ||||
| type MTU = types.MTU | ||||
| 
 | ||||
| // NodeState represents the active and previous configuration of an Yggdrasil | ||||
| // node. A NodeState object is returned when starting an Yggdrasil node. Note | ||||
| // that this structure and related functions are likely to disappear soon. | ||||
|  | @ -72,7 +69,7 @@ type NodeConfig struct { | |||
| 	PrivateKey          string                 `comment:"Your private signing key. DO NOT share this with anyone!"` | ||||
| 	LinkLocalTCPPort    uint16                 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."` | ||||
| 	IfName              string                 `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."` | ||||
| 	IfMTU               MTU                    `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."` | ||||
| 	IfMTU               uint16                 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."` | ||||
| 	SessionFirewall     SessionFirewall        `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."` | ||||
| 	NodeInfoPrivacy     bool                   `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."` | ||||
| 	NodeInfo            map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."` | ||||
|  |  | |||
|  | @ -1,7 +1,5 @@ | |||
| package defaults | ||||
| 
 | ||||
| import "github.com/yggdrasil-network/yggdrasil-go/src/types" | ||||
| 
 | ||||
| // Defines which parameters are expected by default for configuration on a | ||||
| // specific platform. These values are populated in the relevant defaults_*.go | ||||
| // for the platform being targeted. They must be set. | ||||
|  | @ -16,7 +14,7 @@ type platformDefaultParameters struct { | |||
| 	DefaultMulticastInterfaces []string | ||||
| 
 | ||||
| 	// TUN/TAP | ||||
| 	MaximumIfMTU  types.MTU | ||||
| 	DefaultIfMTU  types.MTU | ||||
| 	MaximumIfMTU  uint16 | ||||
| 	DefaultIfMTU  uint16 | ||||
| 	DefaultIfName string | ||||
| } | ||||
|  |  | |||
|  | @ -1,13 +1,34 @@ | |||
| package multicast | ||||
| 
 | ||||
| import "github.com/yggdrasil-network/yggdrasil-go/src/admin" | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/admin" | ||||
| ) | ||||
| 
 | ||||
| type GetMulticastInterfacesRequest struct{} | ||||
| type GetMulticastInterfacesResponse struct { | ||||
| 	Interfaces []string `json:"multicast_interfaces"` | ||||
| } | ||||
| 
 | ||||
| func (m *Multicast) getMulticastInterfacesHandler(req *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error { | ||||
| 	res.Interfaces = []string{} | ||||
| 	for _, v := range m.Interfaces() { | ||||
| 		res.Interfaces = append(res.Interfaces, v.Name) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (m *Multicast) SetupAdminHandlers(a *admin.AdminSocket) { | ||||
| 	a.AddHandler("getMulticastInterfaces", []string{}, func(in admin.Info) (admin.Info, error) { | ||||
| 		var intfs []string | ||||
| 		for _, v := range m.Interfaces() { | ||||
| 			intfs = append(intfs, v.Name) | ||||
| 	_ = a.AddHandler("getMulticastInterfaces", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetMulticastInterfacesRequest{} | ||||
| 		res := &GetMulticastInterfacesResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return admin.Info{"multicast_interfaces": intfs}, nil | ||||
| 		if err := m.getMulticastInterfacesHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return res, nil | ||||
| 	}) | ||||
| } | ||||
|  |  | |||
|  | @ -1,57 +1,31 @@ | |||
| package tuntap | ||||
| 
 | ||||
| import ( | ||||
| 	//"encoding/hex" | ||||
| 	//"errors" | ||||
| 	//"fmt" | ||||
| 	//"net" | ||||
| 	"encoding/json" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/admin" | ||||
| ) | ||||
| 
 | ||||
| func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) { | ||||
| 	a.AddHandler("getTunTap", []string{}, func(in admin.Info) (r admin.Info, e error) { | ||||
| 		defer func() { | ||||
| 			if err := recover(); err != nil { | ||||
| 				r = admin.Info{"none": admin.Info{}} | ||||
| 				e = nil | ||||
| 			} | ||||
| 		}() | ||||
| type GetTUNRequest struct{} | ||||
| type GetTUNResponse map[string]uint16 | ||||
| 
 | ||||
| 		return admin.Info{ | ||||
| 			t.Name(): admin.Info{ | ||||
| 				"mtu": t.mtu, | ||||
| 			}, | ||||
| 		}, nil | ||||
| 	}) | ||||
| 	/* | ||||
| 			// TODO: rewrite this as I'm fairly sure it doesn't work right on many | ||||
| 			// platforms anyway, but it may require changes to Water | ||||
| 		  a.AddHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in Info) (Info, error) { | ||||
| 		    // Set sane defaults | ||||
| 		    iftapmode := defaults.GetDefaults().DefaultIfTAPMode | ||||
| 		    ifmtu := defaults.GetDefaults().DefaultIfMTU | ||||
| 		    // Has TAP mode been specified? | ||||
| 		    if tap, ok := in["tap_mode"]; ok { | ||||
| 		      iftapmode = tap.(bool) | ||||
| func (t *TunAdapter) getTUNHandler(req *GetTUNRequest, res *GetTUNResponse) error { | ||||
| 	res = &GetTUNResponse{ | ||||
| 		t.Name(): t.MTU(), | ||||
| 	} | ||||
| 		    // Check we have enough params for MTU | ||||
| 		    if mtu, ok := in["mtu"]; ok { | ||||
| 		      if mtu.(float64) >= 1280 && ifmtu <= defaults.GetDefaults().MaximumIfMTU { | ||||
| 		        ifmtu = int(in["mtu"].(float64)) | ||||
| 		      } | ||||
| 		    } | ||||
| 		    // Start the TUN adapter | ||||
| 		    if err := a.startTunWithMTU(in["name"].(string), iftapmode, ifmtu); err != nil { | ||||
| 		      return Info{}, errors.New("Failed to configure adapter") | ||||
| 		    } else { | ||||
| 		      return Info{ | ||||
| 		        a.core.router.tun.iface.Name(): Info{ | ||||
| 		          "tap_mode": a.core.router.tun.iface.IsTAP(), | ||||
| 		          "mtu":      ifmtu, | ||||
| 		        }, | ||||
| 		      }, nil | ||||
| 		    } | ||||
| 		  }) | ||||
| 	*/ | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) { | ||||
| 	_ = a.AddHandler("getTunTap", []string{}, func(in json.RawMessage) (interface{}, error) { | ||||
| 		req := &GetTUNRequest{} | ||||
| 		res := &GetTUNResponse{} | ||||
| 		if err := json.Unmarshal(in, &req); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if err := t.getTUNHandler(req, res); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return res, nil | ||||
| 	}) | ||||
| } | ||||
|  |  | |||
|  | @ -23,11 +23,10 @@ import ( | |||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/config" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/defaults" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/types" | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" | ||||
| ) | ||||
| 
 | ||||
| type MTU = types.MTU | ||||
| type MTU uint16 | ||||
| 
 | ||||
| // TunAdapter represents a running TUN interface and extends the | ||||
| // yggdrasil.Adapter type. In order to use the TUN adapter with Yggdrasil, you | ||||
|  | @ -40,7 +39,7 @@ type TunAdapter struct { | |||
| 	log         *log.Logger | ||||
| 	addr        address.Address | ||||
| 	subnet      address.Subnet | ||||
| 	mtu         MTU | ||||
| 	mtu         uint16 | ||||
| 	iface       tun.Device | ||||
| 	phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below | ||||
| 	//mutex        sync.RWMutex // Protects the below | ||||
|  | @ -56,7 +55,7 @@ func (tun *TunAdapter) SetSessionGatekeeper(gatekeeper func(pubkey ed25519.Publi | |||
| 
 | ||||
| // Gets the maximum supported MTU for the platform based on the defaults in | ||||
| // defaults.GetDefaults(). | ||||
| func getSupportedMTU(mtu MTU) MTU { | ||||
| func getSupportedMTU(mtu uint16) uint16 { | ||||
| 	if mtu < 1280 { | ||||
| 		return 1280 | ||||
| 	} | ||||
|  | @ -78,7 +77,7 @@ func (tun *TunAdapter) Name() string { | |||
| // MTU gets the adapter's MTU. This can range between 1280 and 65535, although | ||||
| // the maximum value is determined by your platform. The returned value will | ||||
| // never exceed that of MaximumMTU(). | ||||
| func (tun *TunAdapter) MTU() MTU { | ||||
| func (tun *TunAdapter) MTU() uint16 { | ||||
| 	return getSupportedMTU(tun.mtu) | ||||
| } | ||||
| 
 | ||||
|  | @ -89,14 +88,14 @@ func DefaultName() string { | |||
| 
 | ||||
| // DefaultMTU gets the default TUN interface MTU for your platform. This can | ||||
| // be as high as MaximumMTU(), depending on platform, but is never lower than 1280. | ||||
| func DefaultMTU() MTU { | ||||
| func DefaultMTU() uint16 { | ||||
| 	return defaults.GetDefaults().DefaultIfMTU | ||||
| } | ||||
| 
 | ||||
| // MaximumMTU returns the maximum supported TUN interface MTU for your | ||||
| // platform. This can be as high as 65535, depending on platform, but is never | ||||
| // lower than 1280. | ||||
| func MaximumMTU() MTU { | ||||
| func MaximumMTU() uint16 { | ||||
| 	return defaults.GetDefaults().MaximumIfMTU | ||||
| } | ||||
| 
 | ||||
|  | @ -151,7 +150,7 @@ func (tun *TunAdapter) _start() error { | |||
| 	} | ||||
| 	mtu := current.IfMTU | ||||
| 	if tun.core.MTU() < uint64(mtu) { | ||||
| 		mtu = MTU(tun.core.MTU()) | ||||
| 		mtu = uint16(tun.core.MTU()) | ||||
| 	} | ||||
| 	if err := tun.setup(current.IfName, addr, mtu); err != nil { | ||||
| 		return err | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| // Configures the "utun" adapter with the correct IPv6 address and MTU. | ||||
| func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error { | ||||
| func (tun *TunAdapter) setup(ifname string, addr string, mtu uint16) error { | ||||
| 	if ifname == "auto" { | ||||
| 		ifname = "utun" | ||||
| 	} | ||||
|  | @ -25,8 +25,8 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error { | |||
| 		panic(err) | ||||
| 	} | ||||
| 	tun.iface = iface | ||||
| 	if mtu, err := iface.MTU(); err == nil { | ||||
| 		tun.mtu = getSupportedMTU(MTU(mtu)) | ||||
| 	if m, err := iface.MTU(); err == nil { | ||||
| 		tun.mtu = getSupportedMTU(uint16(m)) | ||||
| 	} else { | ||||
| 		tun.mtu = 0 | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,3 +0,0 @@ | |||
| package types | ||||
| 
 | ||||
| type MTU uint16 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Neil Alexander
						Neil Alexander