235 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package utility
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"net"
 | 
						|
	"net/url"
 | 
						|
	"sort"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/gin-gonic/gin"
 | 
						|
)
 | 
						|
 | 
						|
func GetIp(ctx *gin.Context) string {
 | 
						|
	ip := ctx.ClientIP()
 | 
						|
	if len(ip) > 0 {
 | 
						|
		return ip
 | 
						|
	}
 | 
						|
	return ""
 | 
						|
}
 | 
						|
 | 
						|
// ExternalIP get external ip. 获取外部的ip
 | 
						|
func ExternalIP() (res []string) {
 | 
						|
	inters, err := net.Interfaces()
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	for _, inter := range inters {
 | 
						|
		if !strings.HasPrefix(inter.Name, "lo") {
 | 
						|
			addrs, err := inter.Addrs()
 | 
						|
			if err != nil {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			for _, addr := range addrs {
 | 
						|
				if ipNet, ok := addr.(*net.IPNet); ok {
 | 
						|
					if ipNet.IP.IsLoopback() || ipNet.IP.IsLinkLocalMulticast() || ipNet.IP.IsLinkLocalUnicast() {
 | 
						|
						continue
 | 
						|
					}
 | 
						|
					if ip4 := ipNet.IP.To4(); ip4 != nil {
 | 
						|
						switch true {
 | 
						|
						case ip4[0] == 10:
 | 
						|
							continue
 | 
						|
						case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
 | 
						|
							continue
 | 
						|
						case ip4[0] == 192 && ip4[1] == 168:
 | 
						|
							continue
 | 
						|
						default:
 | 
						|
							res = append(res, ipNet.IP.String())
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// InternalIP get internal ip. 获取内部的ip
 | 
						|
func InternalIP() string {
 | 
						|
	inters, err := net.Interfaces()
 | 
						|
	if err != nil {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	for _, inter := range inters {
 | 
						|
		if inter.Flags&net.FlagUp == net.FlagUp {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if !strings.HasPrefix(inter.Name, "lo") {
 | 
						|
			addrs, err := inter.Addrs()
 | 
						|
			if err != nil {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			for _, addr := range addrs {
 | 
						|
				if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
 | 
						|
					if ipnet.IP.To4() != nil {
 | 
						|
						return ipnet.IP.String()
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ""
 | 
						|
}
 | 
						|
 | 
						|
// GetFreePort gets a free port. 获得一个自由端口
 | 
						|
func GetFreePort() (port int, err error) {
 | 
						|
	listener, err := net.Listen("tcp", "127.0.0.1:0")
 | 
						|
	if err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
	defer listener.Close()
 | 
						|
 | 
						|
	addr := listener.Addr().String()
 | 
						|
	_, portString, err := net.SplitHostPort(addr)
 | 
						|
	if err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
 | 
						|
	return strconv.Atoi(portString)
 | 
						|
}
 | 
						|
 | 
						|
// ParseRpcAddress parses rpc address such as tcp@127.0.0.1:8972  quic@192.168.1.1:9981
 | 
						|
func ParseRpcAddress(addr string) (network string, ip string, port int, err error) {
 | 
						|
	ati := strings.Index(addr, "@")
 | 
						|
	if ati <= 0 {
 | 
						|
		return "", "", 0, errors.New("invalid rpc address: " + addr)
 | 
						|
	}
 | 
						|
 | 
						|
	network = addr[:ati]
 | 
						|
	addr = addr[ati+1:]
 | 
						|
 | 
						|
	var portStr string
 | 
						|
	ip, portStr, err = net.SplitHostPort(addr)
 | 
						|
	if err != nil {
 | 
						|
		return "", "", 0, err
 | 
						|
	}
 | 
						|
 | 
						|
	port, err = strconv.Atoi(portStr)
 | 
						|
	return network, ip, port, err
 | 
						|
}
 | 
						|
 | 
						|
func ConvertMeta2Map(meta string) map[string]string {
 | 
						|
	var rt = make(map[string]string)
 | 
						|
 | 
						|
	if meta == "" {
 | 
						|
		return rt
 | 
						|
	}
 | 
						|
 | 
						|
	v, err := url.ParseQuery(meta)
 | 
						|
	if err != nil {
 | 
						|
		return rt
 | 
						|
	}
 | 
						|
 | 
						|
	for key := range v {
 | 
						|
		rt[key] = v.Get(key)
 | 
						|
	}
 | 
						|
	return rt
 | 
						|
}
 | 
						|
 | 
						|
func ConvertMap2String(meta map[string]string) string {
 | 
						|
	var buf strings.Builder
 | 
						|
	keys := make([]string, 0, len(meta))
 | 
						|
	for k := range meta {
 | 
						|
		keys = append(keys, k)
 | 
						|
	}
 | 
						|
	sort.Strings(keys)
 | 
						|
	for _, k := range keys {
 | 
						|
		vs := meta[k]
 | 
						|
		keyEscaped := url.QueryEscape(k)
 | 
						|
		if buf.Len() > 0 {
 | 
						|
			buf.WriteByte('&')
 | 
						|
		}
 | 
						|
		buf.WriteString(keyEscaped)
 | 
						|
		buf.WriteByte('=')
 | 
						|
		buf.WriteString(url.QueryEscape(vs))
 | 
						|
	}
 | 
						|
	return buf.String()
 | 
						|
}
 | 
						|
 | 
						|
// ExternalIPV4 gets external IPv4 address of this server.
 | 
						|
func ExternalIPV4() (string, error) {
 | 
						|
	ifaces, err := net.Interfaces()
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	for _, iface := range ifaces {
 | 
						|
		if iface.Flags&net.FlagUp == 0 {
 | 
						|
			continue // interface down
 | 
						|
		}
 | 
						|
		if iface.Flags&net.FlagLoopback != 0 {
 | 
						|
			continue // loopback interface
 | 
						|
		}
 | 
						|
		addrs, err := iface.Addrs()
 | 
						|
		if err != nil {
 | 
						|
			return "", err
 | 
						|
		}
 | 
						|
		for _, addr := range addrs {
 | 
						|
			var ip net.IP
 | 
						|
			switch v := addr.(type) {
 | 
						|
			case *net.IPNet:
 | 
						|
				ip = v.IP
 | 
						|
			case *net.IPAddr:
 | 
						|
				ip = v.IP
 | 
						|
			}
 | 
						|
			if ip == nil || ip.IsLoopback() {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			ip = ip.To4()
 | 
						|
			if ip == nil {
 | 
						|
				continue // not an ipv4 address
 | 
						|
			}
 | 
						|
			return ip.String(), nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return "", errors.New("are you connected to the network?")
 | 
						|
}
 | 
						|
 | 
						|
// ExternalIPV6 gets external IPv6 address of this server.
 | 
						|
func ExternalIPV6() (string, error) {
 | 
						|
	ifaces, err := net.Interfaces()
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	for _, iface := range ifaces {
 | 
						|
		if iface.Flags&net.FlagUp == 0 {
 | 
						|
			continue // interface down
 | 
						|
		}
 | 
						|
		if iface.Flags&net.FlagLoopback != 0 {
 | 
						|
			continue // loopback interface
 | 
						|
		}
 | 
						|
		addrs, err := iface.Addrs()
 | 
						|
		if err != nil {
 | 
						|
			return "", err
 | 
						|
		}
 | 
						|
		for _, addr := range addrs {
 | 
						|
			var ip net.IP
 | 
						|
			switch v := addr.(type) {
 | 
						|
			case *net.IPNet:
 | 
						|
				ip = v.IP
 | 
						|
			case *net.IPAddr:
 | 
						|
				ip = v.IP
 | 
						|
			}
 | 
						|
			if ip == nil || ip.IsLoopback() {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			ip = ip.To16()
 | 
						|
			if ip == nil {
 | 
						|
				continue // not an ipv4 address
 | 
						|
			}
 | 
						|
			return ip.String(), nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return "", errors.New("are you connected to the network?")
 | 
						|
}
 |