Antizapret fails when several threads update the config
This commit is contained in:
		
							parent
							
								
									58fa6e6a95
								
							
						
					
					
						commit
						2b750b47d2
					
				@ -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,62 +8,62 @@ 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:
 | 
					 | 
				
			||||||
            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)
 | 
					        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 +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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user