Merge pull request #81 from ElijahCapricorn/master

Antizapret fails when several threads update the config
pull/15/head
DiMartinoXBMC 2017-06-01 20:32:18 +03:00 committed by GitHub
commit 2e07beedd5
1 changed files with 57 additions and 54 deletions

View File

@ -1,69 +1,72 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os, re, fnmatch, threading, urllib2 import os, re, fnmatch, threading, urllib2, time, shelve, anydbm
from contextlib import contextmanager, closing from contextlib import contextmanager, closing
from functions import log, debug, tempdir from functions import log, debug, tempdir
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'] try:
if not pac_config: shelf = shelve.open(filename)
log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL) except anydbm.error:
try: os.remove(filename)
pac_data = urllib2.urlopen(PAC_URL).read() shelf = shelve.open(filename)
except:
pac_data = ""
r = re.search(r"\"PROXY (.*); DIRECT", pac_data) created_at = 0
if r: data = {}
pac_config["server"] = r.group(1)
pac_config["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data))) if 'created_at' in shelf:
else: created_at = shelf['created_at']
pac_config["server"] = None
pac_config["domains"] = [] if 'data' in shelf:
d.close() data = shelf['data']
_config = pac_config
return _config 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)
try:
pac_data = urllib2.urlopen(PAC_URL).read()
except:
pac_data = ""
r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
if r:
data["server"] = r.group(1)
data["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
else:
data["server"] = None
data["domains"] = []
shelf.clear()
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 +79,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)
@ -108,4 +112,3 @@ def url_get(url, params={}, headers={}, post = None):
except urllib2.HTTPError as e: except urllib2.HTTPError as e:
log("[antizapret]: HTTP Error(%s): %s" % (e.errno, e.strerror)) log("[antizapret]: HTTP Error(%s): %s" % (e.errno, e.strerror))
return None return None