1 from __future__
import print_function
19 return maxminddb.open_database(dbname)
21 gidb=
"/var/lib/cvmfs-server/geo/GeoLite2-City.mmdb"
29 geo_cache_max_entries = 100000
38 gilock = threading.Lock()
39 namelock = threading.Lock()
45 global gireader, oldgireader
49 if gireader
is None or now > gichecktime + geo_cache_secs:
53 if gireader
is None or now > gichecktime + geo_cache_secs:
54 if oldgireader
is not None:
60 print(
'cvmfs_geo: closed old ' + gidb)
62 modtime = os.stat(gidb).st_mtime
63 if modtime != gimodtime:
65 oldgireader = gireader
68 print(
'cvmfs_geo: opened ' + gidb)
72 return gireader.get(addr)
77 if (lat1 == lat2)
and (long1 == long2):
82 degrees_to_radians = math.pi/180.0
85 phi1 = (90.0 - lat1)*degrees_to_radians
86 phi2 = (90.0 - lat2)*degrees_to_radians
89 theta1 = long1*degrees_to_radians
90 theta2 = long2*degrees_to_radians
100 cos = (math.sin(phi1)*math.sin(phi2)*math.cos(theta1 - theta2) +
101 math.cos(phi1)*math.cos(phi2))
102 arc = math.acos( cos )
113 addr_pattern = re.compile(
'^[0-9a-zA-Z.:-]*$')
118 if (len(addr) > 256)
or not addr_pattern.search(addr):
125 return response[
'location']
134 if (len(name) > 256)
or not addr_pattern.search(name):
139 if name
in geo_cache:
140 (stamp, gir) = geo_cache[name]
141 if now <= stamp + geo_cache_secs:
147 geo_cache[name] = (now, gir)
148 elif len(geo_cache) >= geo_cache_max_entries:
157 ai = socket.getaddrinfo(name,80,0,0,socket.IPPROTO_TCP)
163 if info[0] == socket.AF_INET:
169 if info[0] == socket.AF_INET6:
173 if 'location' in gir:
174 gir = gir[
'location']
179 if gir ==
None and name
in geo_cache:
181 gir = geo_cache[name][1]
183 geo_cache[name] = (now, gir)
203 for server
in servers:
207 if gir_server
is None:
210 if gir_server
is None:
216 gir_rem[
'longitude'],
217 gir_server[
'latitude'],
218 gir_server[
'longitude'])
225 i = bisect.bisect(arcs, arc)
230 return [onegood, indexes]
249 def api(path_info, repo_name, version, start_response, environ):
251 slash = path_info.find(
'/')
255 caching_string = path_info[0:slash]
256 servers = path_info[slash+1:].split(
',')
258 if caching_string ==
"_namelookups_":
263 now = int(time.time())
266 if 'HTTP_CF_CONNECTING_IP' in environ:
272 if caching_string.find(
'.'):
277 if 'HTTP_CF_CONNECTING_IP' in environ:
279 gir_rem =
addr_geoinfo(now, environ[
'HTTP_CF_CONNECTING_IP'])
280 if gir_rem
is None and 'HTTP_X_FORWARDED_FOR' in environ:
284 forwarded_for = environ[
'HTTP_X_FORWARDED_FOR']
285 start = forwarded_for.rfind(
' ') + 1
287 start = forwarded_for.rfind(
',') + 1
289 if gir_rem
is None and 'REMOTE_ADDR' in environ:
296 if '+PXYSEP+' in servers:
300 pxysep = servers.index(
'+PXYSEP+')
302 onegood, pxyindexes = \
305 gir_pxy =
name_geoinfo(now, servers[pxysep+1+pxyindexes[0]])
306 if not gir_pxy
is None:
308 onegood, hostindexes = \
310 indexes = hostindexes + list(pxysep+1+i
for i
in pxyindexes)
314 indexes.append(pxysep)
322 response_body =
','.join(str(i+1)
for i
in indexes) +
'\n'
def distance_on_unit_sphere