Antizapret fails when several threads update the config

pull/15/head^2
elijahcapricorn 2017-05-07 20:31:36 +03:00
parent 58fa6e6a95
commit 2b750b47d2
1 changed files with 52 additions and 51 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os, re, fnmatch, threading, urllib2 import os, re, fnmatch, threading, urllib2, time, shelve
from contextlib import contextmanager, closing from contextlib import contextmanager, closing
from functions import log, debug, tempdir from functions import log, debug, tempdir
@ -8,46 +8,34 @@ LOCKS = {}
PAC_URL = "http://antizapret.prostovpn.org/proxy.pac" PAC_URL = "http://antizapret.prostovpn.org/proxy.pac"
CACHE_DIR = tempdir() CACHE_DIR = tempdir()
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36" USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
CONFIG_LOCK = threading.Lock()
if not os.path.exists(CACHE_DIR): if not os.path.exists(CACHE_DIR):
os.makedirs(CACHE_DIR) os.makedirs(CACHE_DIR)
CACHE = 24 * 3600 # 24 hour caching CACHE_LIFETIME = 24 * 3600 # 24 hour caching
#@contextmanager
def shelf(filename, ttl=0):
import shelve
filename = os.path.join(CACHE_DIR, filename)
with LOCKS.get(filename, threading.RLock()):
# with closing(shelve.open(filename, writeback=True)) as d:
d = shelve.open(filename, writeback=True)
#try:
if True:
import time
if not dict(d):
log('xxx')
d.update({
"created_at": time.time(),
"data": {},
})
elif ttl > 0 and (time.time() - d["created_at"]) > ttl:
log('xxx')
d["created_at"] = time.time()
d["data"] = {}
return d
#except:
# d.close()
# raise
_config = {}
def config(): def config():
global _config shelf = None
if not _config: try:
# with shelf("antizapret.pac_config", ttl=CACHE) as pac_config: CONFIG_LOCK.acquire()
d = shelf("antizapret.pac_config2", ttl=CACHE) filename = os.path.join(CACHE_DIR, "antizapret.pac_config2")
pac_config = d['data'] shelf = shelve.open(filename)
if not pac_config:
created_at = 0
data = {}
if 'created_at' in shelf:
created_at = shelf['created_at']
if 'data' in shelf:
data = shelf['data']
if((time.time() - created_at) <= CACHE_LIFETIME
and 'domains' in data
and len(data['domains']) > 0):
return data
log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL) log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
try: try:
pac_data = urllib2.urlopen(PAC_URL).read() pac_data = urllib2.urlopen(PAC_URL).read()
@ -56,14 +44,26 @@ def config():
r = re.search(r"\"PROXY (.*); DIRECT", pac_data) r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
if r: if r:
pac_config["server"] = r.group(1) data["server"] = r.group(1)
pac_config["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data))) data["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
else: else:
pac_config["server"] = None data["server"] = None
pac_config["domains"] = [] data["domains"] = []
d.close()
_config = pac_config shelf.clear()
return _config shelf.update({
"created_at": time.time(),
"data": data,
})
return data
except Exception as ex:
debug("[antizapret]: " + str(ex))
raise
finally:
if shelf:
shelf.close()
if CONFIG_LOCK.locked():
CONFIG_LOCK.release()
class AntizapretProxyHandler(urllib2.ProxyHandler, object): class AntizapretProxyHandler(urllib2.ProxyHandler, object):
def __init__(self): def __init__(self):
@ -76,7 +76,8 @@ class AntizapretProxyHandler(urllib2.ProxyHandler, object):
def proxy_open(self, req, proxy, type): def proxy_open(self, req, proxy, type):
import socket import socket
if socket.gethostbyname(req.get_host().split(":")[0]) in self.config["domains"]: hostname = req.get_host().split(":")[0]
if socket.gethostbyname(hostname) in self.config["domains"] or hostname in self.config["domains"]:
debug("[antizapret]: Pass request through proxy " + self.config["server"]) debug("[antizapret]: Pass request through proxy " + self.config["server"])
return urllib2.ProxyHandler.proxy_open(self, req, self.config["server"], type) return urllib2.ProxyHandler.proxy_open(self, req, self.config["server"], type)