Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
base repository: arlolra/flashproxy
base: master
head repository: arlolra/flashproxy
compare: 7823
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 3 files changed
  • 0 comments
  • 1 contributor
Commits on Jun 11, 2013
Adds an ordereddict.py to support Python < 2.7
Showing with 164 additions and 4 deletions.
  1. +1 −1 facilitator/Makefile
  2. +36 −3 facilitator/facilitator
  3. +127 −0 facilitator/ordereddict.py
@@ -6,7 +6,7 @@ all:

install:
mkdir -p $(BINDIR)
cp -f facilitator facilitator-email-poller facilitator-reg-daemon facilitator-reg facilitator.cgi fac.py $(BINDIR)
cp -f facilitator facilitator-email-poller facilitator-reg-daemon facilitator-reg facilitator.cgi fac.py ordereddict.py $(BINDIR)
cp -f init.d/facilitator init.d/facilitator-email-poller init.d/facilitator-reg-daemon /etc/init.d/

clean:
@@ -10,6 +10,11 @@ import time

import fac

# from collections import OrderedDict
# requires python >= 2.7
# see: https://pypi.python.org/pypi/ordereddict
from ordereddict import OrderedDict

LISTEN_ADDRESS = "127.0.0.1"
DEFAULT_LISTEN_PORT = 9002
DEFAULT_RELAY_PORT = 9001
@@ -232,14 +237,17 @@ class Handler(SocketServer.StreamRequestHandler):
log(u"syntax error in proxy address %s: %s" % (safe_str(repr(proxy_spec)), safe_str(repr(str(e)))))
self.send_error()
return False

rate_limit, check_back_in = get_check_back_in_for_proxy(proxy_addr)
if rate_limit:
log(u"proxy address %s was rate limited" % safe_str(repr(proxy_spec)))
print >> self.wfile, fac.render_transaction("NONE", ("CHECK-BACK-IN", str(check_back_in)))
return True
try:
reg = get_reg_for_proxy(proxy_addr)
except Exception, e:
log(u"error getting reg for proxy address %s: %s" % (safe_str(repr(proxy_spec)), safe_str(repr(str(e)))))
self.send_error()
return False
check_back_in = get_check_back_in_for_proxy(proxy_addr)
if reg:
log(u"proxy gets %s, relay %s (now %d)" %
(safe_str(unicode(reg)), options.relay_spec, num_regs()))
@@ -284,6 +292,22 @@ class Handler(SocketServer.StreamRequestHandler):
class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True

class LRU(OrderedDict):
def __init__(self, *args, **kwds):
self.size = kwds.pop("size", None)
if self.size is None:
raise ValueError("Expected a size for the LRU")
OrderedDict.__init__(self, *args, **kwds)
self.limit()
def __setitem__(self, key, value):
if key in self:
del self[key]
OrderedDict.__setitem__(self, key, value)
self.limit()
def limit(self):
while len(self) > self.size:
self.popitem(last=False)

# Separate pools for IPv4 and IPv6 clients.
REGS_IPV4 = RegSet()
REGS_IPV6 = RegSet()
@@ -315,9 +339,18 @@ def get_reg_for_proxy(proxy_addr):
REGS = regs_for_af(af)
return REGS.fetch()

# Keep track of the latest <size> proxies for rate limiting.
RL_PROXIES = LRU(size=10000)

def get_check_back_in_for_proxy(proxy_addr):
"""Get a CHECK-BACK-IN interval suitable for this proxy."""
return POLL_INTERVAL
now = int(time.time())
last_time = RL_PROXIES.get(proxy_addr, (now - POLL_INTERVAL))
delta = now - last_time
if delta >= POLL_INTERVAL:
RL_PROXIES[proxy_addr] = now
return False, POLL_INTERVAL
return True, (POLL_INTERVAL - delta)

def put_reg(reg):
"""Add a registration."""
@@ -0,0 +1,127 @@
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

from UserDict import DictMixin

class OrderedDict(dict, DictMixin):

def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)

def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)

def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)

def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev

def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]

def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]

def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
if last:
key = reversed(self).next()
else:
key = iter(self).next()
value = self.pop(key)
return key, value

def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)

def keys(self):
return list(self)

setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems

def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())

def copy(self):
return self.__class__(self)

@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d

def __eq__(self, other):
if isinstance(other, OrderedDict):
if len(self) != len(other):
return False
for p, q in zip(self.items(), other.items()):
if p != q:
return False
return True
return dict.__eq__(self, other)

def __ne__(self, other):
return not self == other

No commit comments for this range