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  }