go.temporal.io/server@v1.23.0/common/config/localip.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package config 26 27 // ** This code is copied from tchannel, we would like to not take dependency on tchannel code ** 28 29 import ( 30 "errors" 31 "net" 32 ) 33 34 // scoreAddr scores how likely the given addr is to be a remote address and returns the 35 // IP to use when listening. Any address which receives a negative score should not be used. 36 // Scores are calculated as: 37 // -1 for any unknown IP addreseses. 38 // +300 for IPv4 addresses 39 // +100 for non-local addresses, extra +100 for "up" interaces. 40 func scoreAddr(iface net.Interface, addr net.Addr) (int, net.IP) { 41 var ip net.IP 42 if netAddr, ok := addr.(*net.IPNet); ok { 43 ip = netAddr.IP 44 } else if netIP, ok := addr.(*net.IPAddr); ok { 45 ip = netIP.IP 46 } else { 47 return -1, nil 48 } 49 50 var score int 51 if ip.To4() != nil { 52 score += 300 53 } 54 if iface.Flags&net.FlagLoopback == 0 && !ip.IsLoopback() { 55 score += 100 56 if iface.Flags&net.FlagUp != 0 { 57 score += 100 58 } 59 } 60 return score, ip 61 } 62 63 // ListenIP returns the IP to bind to in Listen. It tries to find an IP that can be used 64 // by other machines to reach this machine. 65 func ListenIP() (net.IP, error) { 66 interfaces, err := net.Interfaces() 67 if err != nil { 68 return nil, err 69 } 70 71 bestScore := -1 72 var bestIP net.IP 73 // Select the highest scoring IP as the best IP. 74 for _, iface := range interfaces { 75 addrs, err := iface.Addrs() 76 if err != nil { 77 // Skip this interface if there is an error. 78 continue 79 } 80 81 for _, addr := range addrs { 82 score, ip := scoreAddr(iface, addr) 83 if score > bestScore { 84 bestScore = score 85 bestIP = ip 86 } 87 } 88 } 89 90 if bestScore == -1 { 91 return nil, errors.New("no addresses to listen on") 92 } 93 94 return bestIP, nil 95 } 96 97 func mustParseMAC(s string) net.HardwareAddr { 98 addr, err := net.ParseMAC(s) 99 if err != nil { 100 panic(err) 101 } 102 return addr 103 }