mirror of
https://github.com/status-im/status-go.git
synced 2026-08-28 07:31:07 +00:00
`server` was one Go package doing three unrelated jobs. Each moves to where it belongs: server/pairing/ -> services/pairing/ server_media*.go, handlers*.go, testdata/ -> services/media/ server.go, certs.go, ips.go, timeout.go, device.go, listen_*.go, servertest/ -> internal/httpserver/ MediaServer is renamed to media.Server (and NewMediaServer to media.NewServer) now that it has a package to be named against. Deliberately untouched: StatusNode.MediaServer(), which is an accessor method rather than the type, and the unrelated identifiers that only share the prefix (MediaServerImageID, MediaServerContactIcon, MediaServerEnableTLS, ...). Two identifiers had to be reassigned to make the boundary clean: - certs.go held both the generic X509/TLS helpers and the media server's process-global certificate. Split: the generic half stays in internal/httpserver, generateMediaTLSCert and PublicMediaTLSCert move to services/media. - HandlerPatternMap was declared in handlers.go but is a plain HTTP type that server.go depends on; it moves to internal/httpserver. The media server URL tests moved with the type, and reached three unexported Server fields they could touch while everything shared a package. internal/httpserver now exposes ListeningAddr() and CachedPort() (both reasonable API) plus a clearly-marked SetURLStateForTest. Nothing else crossed the boundary, and the split is one-directional: services/media and services/pairing import internal/httpserver, never the reverse. refs #7067
204 lines
4.7 KiB
Go
204 lines
4.7 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"net"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/status-im/status-go/internal/logutils"
|
|
"github.com/status-im/status-go/internal/platform"
|
|
)
|
|
|
|
var (
|
|
LocalHostIP = net.IP{127, 0, 0, 1}
|
|
Localhost = "localhost"
|
|
)
|
|
|
|
func GetOutboundIP() (net.IP, error) {
|
|
conn, err := net.Dial("udp", "255.255.255.255:8080")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer conn.Close()
|
|
|
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
|
|
|
return localAddr.IP, nil
|
|
}
|
|
|
|
// addrToIPNet casts addr to IPNet.
|
|
// Returns nil if addr is not of IPNet type.
|
|
func addrToIPNet(addr net.Addr) *net.IPNet {
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
return v
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// filterAddressesForPairingServer filters private unicast addresses.
|
|
// ips is a 2-dimensional array, where each sub-array is a list of IP
|
|
// addresses for a single network interface.
|
|
func filterAddressesForPairingServer(ips [][]net.IP) []net.IP {
|
|
var result = map[string]net.IP{}
|
|
|
|
for _, niIps := range ips {
|
|
var ipv4, ipv6 []net.IP
|
|
|
|
for _, ip := range niIps {
|
|
|
|
// Only take private global unicast addrs
|
|
if !ip.IsGlobalUnicast() || !ip.IsPrivate() {
|
|
continue
|
|
}
|
|
|
|
if v := ip.To4(); v != nil {
|
|
ipv4 = append(ipv4, ip)
|
|
} else {
|
|
ipv6 = append(ipv6, ip)
|
|
}
|
|
}
|
|
|
|
// Prefer IPv4 over IPv6 for shorter connection string
|
|
if len(ipv4) == 0 {
|
|
for _, ip := range ipv6 {
|
|
result[ip.String()] = ip
|
|
}
|
|
} else {
|
|
for _, ip := range ipv4 {
|
|
result[ip.String()] = ip
|
|
}
|
|
}
|
|
}
|
|
|
|
var out []net.IP
|
|
for _, v := range result {
|
|
out = append(out, v)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
// getAndroidLocalIP uses the net dial default ip as the standard Android IP address
|
|
// patches https://github.com/status-im/status-mobile/issues/17156
|
|
// more work required for a more robust implementation, see https://github.com/wlynxg/anet
|
|
func getAndroidLocalIP() ([][]net.IP, error) {
|
|
ip, err := GetOutboundIP()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return [][]net.IP{{ip}}, nil
|
|
}
|
|
|
|
// getLocalAddresses returns an array of all addresses
|
|
// of all available network interfaces.
|
|
func getLocalAddresses() ([][]net.IP, error) {
|
|
// TODO until we can resolve Android errors when calling net.Interfaces() just return the outbound local address.
|
|
// Sorry Android
|
|
if platform.OperatingSystemIs(platform.AndroidPlatform) {
|
|
return getAndroidLocalIP()
|
|
}
|
|
|
|
nis, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var ips [][]net.IP
|
|
|
|
for _, ni := range nis {
|
|
var niIps []net.IP
|
|
|
|
addrs, err := ni.Addrs()
|
|
if err != nil {
|
|
logutils.ZapLogger().Warn("failed to get addresses of network interface",
|
|
zap.String("networkInterface", ni.Name),
|
|
zap.Error(err))
|
|
continue
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
if ipNet := addrToIPNet(addr); ipNet == nil {
|
|
continue
|
|
} else {
|
|
ip = ipNet.IP
|
|
}
|
|
niIps = append(niIps, ip)
|
|
}
|
|
|
|
if len(niIps) > 0 {
|
|
ips = append(ips, niIps)
|
|
}
|
|
}
|
|
|
|
return ips, nil
|
|
}
|
|
|
|
// GetLocalAddressesForPairingServer is a high-level func
|
|
// that returns a list of addresses to be used by local pairing server.
|
|
func GetLocalAddressesForPairingServer() ([]net.IP, error) {
|
|
ips, err := getLocalAddresses()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return filterAddressesForPairingServer(ips), nil
|
|
}
|
|
|
|
// findReachableAddresses returns a filtered remoteIps array,
|
|
// in which each IP matches one or more of given localNets.
|
|
func findReachableAddresses(remoteIPs []net.IP, localNets []net.IPNet) []net.IP {
|
|
var result []net.IP
|
|
for _, localNet := range localNets {
|
|
for _, remoteIP := range remoteIPs {
|
|
if localNet.Contains(remoteIP) {
|
|
result = append(result, remoteIP)
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// getAllAvailableNetworks collects all networks
|
|
// from available network interfaces.
|
|
func getAllAvailableNetworks() ([]net.IPNet, error) {
|
|
var localNets []net.IPNet
|
|
|
|
nis, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, ni := range nis {
|
|
addrs, err := ni.Addrs()
|
|
if err != nil {
|
|
logutils.ZapLogger().Warn("failed to get addresses of network interface",
|
|
zap.String("networkInterface", ni.Name),
|
|
zap.Error(err))
|
|
continue
|
|
}
|
|
|
|
for _, localAddr := range addrs {
|
|
localNets = append(localNets, *addrToIPNet(localAddr))
|
|
}
|
|
}
|
|
return localNets, nil
|
|
}
|
|
|
|
// FindReachableAddressesForPairingClient is a high-level func
|
|
// that returns a reachable server's address to be used by local pairing client.
|
|
func FindReachableAddressesForPairingClient(serverIps []net.IP) ([]net.IP, error) {
|
|
// TODO until we can resolve Android errors when calling net.Interfaces() just noop. Sorry Android
|
|
if platform.OperatingSystemIs(platform.AndroidPlatform) {
|
|
return serverIps, nil
|
|
}
|
|
|
|
nets, err := getAllAvailableNetworks()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return findReachableAddresses(serverIps, nets), nil
|
|
}
|