##// END OF EJS Templates
use netifaces for faster IPython.utils.localinterfaces
MinRK -
Show More
@@ -1,108 +1,164 b''
1 """Simple utility for building a list of local IPs using the socket module.
1 """Simple utility for building a list of local IPs using the socket module.
2 This module defines two constants:
2 This module defines two constants:
3
3
4 LOCALHOST : The loopback interface, or the first interface that points to this
4 LOCALHOST : The loopback interface, or the first interface that points to this
5 machine. It will *almost* always be '127.0.0.1'
5 machine. It will *almost* always be '127.0.0.1'
6
6
7 LOCAL_IPS : A list of IP addresses, loopback first, that point to this machine.
7 LOCAL_IPS : A list of IP addresses, loopback first, that point to this machine.
8 This will include LOCALHOST, PUBLIC_IPS, and aliases for all hosts,
9 such as '0.0.0.0'.
8
10
9 PUBLIC_IPS : A list of public IP addresses that point to this machine.
11 PUBLIC_IPS : A list of public IP addresses that point to this machine.
10 Use these to tell remote clients where to find you.
12 Use these to tell remote clients where to find you.
11 """
13 """
12 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
13 # Copyright (C) 2010-2011 The IPython Development Team
15 # Copyright (C) 2010-2011 The IPython Development Team
14 #
16 #
15 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
18
20
19 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
20 # Imports
22 # Imports
21 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
22
24
23 import socket
25 import socket
24
26
25 from .data import uniq_stable
27 from .data import uniq_stable
26
28
27 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
28 # Code
30 # Code
29 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
30
32
31 LOCAL_IPS = []
33 LOCAL_IPS = []
32 PUBLIC_IPS = []
34 PUBLIC_IPS = []
33
35
34 LOCALHOST = '127.0.0.1'
36 LOCALHOST = ''
35
37
36 def _only_once(f):
38 def _only_once(f):
37 """decorator to only run a function once"""
39 """decorator to only run a function once"""
38 f.called = False
40 f.called = False
39 def wrapped():
41 def wrapped():
40 if f.called:
42 if f.called:
41 return
43 return
42 ret = f()
44 ret = f()
43 f.called = True
45 f.called = True
44 return ret
46 return ret
45 return wrapped
47 return wrapped
46
48
47 def _requires_ips(f):
49 def _requires_ips(f):
48 """decorator to ensure load_ips has been run before f"""
50 """decorator to ensure load_ips has been run before f"""
49 def ips_loaded(*args, **kwargs):
51 def ips_loaded(*args, **kwargs):
50 _load_ips()
52 _load_ips()
51 return f(*args, **kwargs)
53 return f(*args, **kwargs)
52 return ips_loaded
54 return ips_loaded
53
55
54 @_only_once
56 def _load_ips_netifaces():
55 def _load_ips():
57 """load ip addresses with netifaces"""
56 """load the IPs that point to this machine
58 import netifaces
59 global LOCALHOST
60 local_ips = []
61 public_ips = []
57
62
58 This function will only ever be called once.
63 # list of iface names, 'lo0', 'eth0', etc.
64 for iface in netifaces.interfaces():
65 # list of ipv4 addrinfo dicts
66 ipv4s = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])
67 for entry in ipv4s:
68 addr = entry.get('addr')
69 if not addr:
70 continue
71 if not (iface.startswith('lo') or addr.startswith('127.')):
72 public_ips.append(addr)
73 elif not LOCALHOST:
74 LOCALHOST = addr
75 local_ips.append(addr)
76 if not LOCALHOST:
77 # we never found a loopback interface (can this ever happen?), assume common default
78 LOCALHOST = '127.0.0.1'
79 local_ips.insert(0, LOCALHOST)
80 local_ips.extend(['0.0.0.0', ''])
81 LOCAL_IPS[:] = uniq_stable(local_ips)
82 PUBLIC_IPS[:] = uniq_stable(public_ips)
83
84 def _load_ips_gethostbyname():
85 """load ip addresses with socket.gethostbyname_ex
86
87 This can be slow.
59 """
88 """
60 global LOCALHOST
89 global LOCALHOST
61 try:
90 try:
62 LOCAL_IPS[:] = socket.gethostbyname_ex('localhost')[2]
91 LOCAL_IPS[:] = socket.gethostbyname_ex('localhost')[2]
63 except socket.error:
92 except socket.error:
64 pass
93 # assume common default
94 LOCAL_IPS[:] = ['127.0.0.1']
65
95
66 try:
96 try:
67 hostname = socket.gethostname()
97 hostname = socket.gethostname()
68 PUBLIC_IPS[:] = socket.gethostbyname_ex(hostname)[2]
98 PUBLIC_IPS[:] = socket.gethostbyname_ex(hostname)[2]
69 # try hostname.local, in case hostname has been short-circuited to loopback
99 # try hostname.local, in case hostname has been short-circuited to loopback
70 if not hostname.endswith('.local') and all(ip.startswith('127') for ip in PUBLIC_IPS):
100 if not hostname.endswith('.local') and all(ip.startswith('127') for ip in PUBLIC_IPS):
71 PUBLIC_IPS[:] = socket.gethostbyname_ex(socket.gethostname() + '.local')[2]
101 PUBLIC_IPS[:] = socket.gethostbyname_ex(socket.gethostname() + '.local')[2]
72 except socket.error:
102 except socket.error:
73 pass
103 pass
74 finally:
104 finally:
75 PUBLIC_IPS[:] = uniq_stable(PUBLIC_IPS)
105 PUBLIC_IPS[:] = uniq_stable(PUBLIC_IPS)
76 LOCAL_IPS.extend(PUBLIC_IPS)
106 LOCAL_IPS.extend(PUBLIC_IPS)
77
107
78 # include all-interface aliases: 0.0.0.0 and ''
108 # include all-interface aliases: 0.0.0.0 and ''
79 LOCAL_IPS.extend(['0.0.0.0', ''])
109 LOCAL_IPS.extend(['0.0.0.0', ''])
80
110
81 LOCAL_IPS[:] = uniq_stable(LOCAL_IPS)
111 LOCAL_IPS[:] = uniq_stable(LOCAL_IPS)
82
112
83 LOCALHOST = LOCAL_IPS[0]
113 LOCALHOST = LOCAL_IPS[0]
84
114
115 def _load_ips_dumb():
116 """Fallback in case of unexpected failure"""
117 global LOCALHOST
118 LOCALHOST = '127.0.0.1'
119 LOCAL_IPS[:] = [LOCALHOST, '0.0.0.0', '']
120 PUBLIC_IPS[:] = []
121
122 @_only_once
123 def _load_ips():
124 """load the IPs that point to this machine
125
126 This function will only ever be called once.
127
128 It will use netifaces to do it quickly if available,
129 otherwise it will fallback on socket.gethostbyname_ex, which can be slow.
130 """
131 try:
132 try:
133 _load_ips_netifaces()
134 except ImportError:
135 _load_ips_gethostbyname()
136 except Exception:
137 # unexpected error shouldn't crash, load dumb default values instead.
138 _load_ips_dumb()
139
140
85 @_requires_ips
141 @_requires_ips
86 def local_ips():
142 def local_ips():
87 """return the IP addresses that point to this machine"""
143 """return the IP addresses that point to this machine"""
88 return LOCAL_IPS
144 return LOCAL_IPS
89
145
90 @_requires_ips
146 @_requires_ips
91 def public_ips():
147 def public_ips():
92 """return the IP addresses for this machine that are visible to other machines"""
148 """return the IP addresses for this machine that are visible to other machines"""
93 return PUBLIC_IPS
149 return PUBLIC_IPS
94
150
95 @_requires_ips
151 @_requires_ips
96 def localhost():
152 def localhost():
97 """return ip for localhost (almost always 127.0.0.1)"""
153 """return ip for localhost (almost always 127.0.0.1)"""
98 return LOCALHOST
154 return LOCALHOST
99
155
100 @_requires_ips
156 @_requires_ips
101 def is_local_ip(ip):
157 def is_local_ip(ip):
102 """does `ip` point to this machine?"""
158 """does `ip` point to this machine?"""
103 return ip in LOCAL_IPS
159 return ip in LOCAL_IPS
104
160
105 @_requires_ips
161 @_requires_ips
106 def is_public_ip(ip):
162 def is_public_ip(ip):
107 """is `ip` a publicly visible address?"""
163 """is `ip` a publicly visible address?"""
108 return ip in PUBLIC_IPS
164 return ip in PUBLIC_IPS
General Comments 0
You need to be logged in to leave comments. Login now