blob: ac8a0625cae7611a0eb55c3a62fe2f874f59d00a [file] [log] [blame]
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07001package internal
2
3import (
4 "fmt"
Suharsh Sivakumard68949c2015-01-26 10:32:23 -08005 "os"
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -07006
Jiri Simsa764efb72014-12-25 20:57:03 -08007 "v.io/core/veyron2/ipc"
8 "v.io/core/veyron2/vlog"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07009
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080010 "v.io/core/veyron/lib/exec"
11 "v.io/core/veyron/lib/flags"
Jiri Simsa764efb72014-12-25 20:57:03 -080012 "v.io/core/veyron/lib/netstate"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070013)
14
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080015// ParseFlags parses all registered flags taking into account overrides from other
16// configuration and environment variables. It must be called by the profile and
17// flags.RuntimeFlags() must be passed to the runtime initialization function. The
18// profile can use or modify the flags as it pleases.
19func ParseFlags(f *flags.Flags) error {
20 handle, err := exec.GetChildHandle()
21 switch err {
22 case exec.ErrNoVersion:
23 // The process has not been started through the veyron exec
24 // library. No further action is needed.
25 case nil:
26 // The process has been started through the veyron exec
27 // library.
28 default:
29 return err
30 }
31
32 // Parse runtime flags.
33 var config map[string]string
34 if handle != nil {
35 config = handle.Config.Dump()
36 }
37 f.Parse(os.Args[1:], config)
38 return nil
39}
40
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070041// IPAddressChooser returns the preferred IP address, which is,
42// a public IPv4 address, then any non-loopback IPv4, then a public
43// IPv6 address and finally any non-loopback/link-local IPv6
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070044func IPAddressChooser(network string, addrs []ipc.Address) ([]ipc.Address, error) {
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070045 if !netstate.IsIPProtocol(network) {
46 return nil, fmt.Errorf("can't support network protocol %q", network)
47 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070048 accessible := netstate.AddrList(addrs)
49
50 // Try and find an address on a interface with a default route.
51 predicates := []netstate.AddressPredicate{netstate.IsPublicUnicastIPv4,
52 netstate.IsUnicastIPv4, netstate.IsPublicUnicastIPv6}
53 for _, predicate := range predicates {
54 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
55 onDefaultRoutes := addrs.Filter(netstate.IsOnDefaultRoute)
56 if len(onDefaultRoutes) > 0 {
57 return onDefaultRoutes, nil
58 }
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070059 }
60 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070061
62 // We failed to find any addresses with default routes, try again
63 // but without the default route requirement.
64 for _, predicate := range predicates {
65 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
66 return addrs, nil
67 }
68 }
69
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070070 return nil, fmt.Errorf("failed to find any usable address for %q", network)
71}
Cosmos Nicolaou43b95352014-10-14 11:09:52 -070072
73// HasPublicIP returns true if the host has at least one public IP address.
74func HasPublicIP(log vlog.Logger) bool {
75 state, err := netstate.GetAccessibleIPs()
76 if err != nil {
77 log.Infof("failed to determine network state: %s", err)
78 return false
79 }
80 any := state.Filter(netstate.IsUnicastIP)
81 if len(any) == 0 {
82 log.Infof("failed to find any usable IP addresses at startup")
83 return false
84 }
85 for _, a := range any {
86 if netstate.IsPublicUnicastIPv4(a) {
87 return true
88 }
89 }
90 return false
91}