diff --git a/src/network/dandelion.py b/src/network/dandelion.py index 06ecca24..bfa85e4e 100644 --- a/src/network/dandelion.py +++ b/src/network/dandelion.py @@ -1,14 +1,19 @@ +""" +src/network/dandelion.py +======================== + +""" + from collections import namedtuple -from random import choice, sample, expovariate +from random import choice, expovariate, sample from threading import RLock from time import time -from bmconfigparser import BMConfigParser import network.connectionpool +import state from debug import logging from queues import invQueue from singleton import Singleton -import state # randomise routes after 600 seconds REASSIGN_INTERVAL = 600 @@ -21,8 +26,12 @@ MAX_STEMS = 2 Stem = namedtuple('Stem', ['child', 'stream', 'timeout']) + @Singleton -class Dandelion(): +class Dandelion: + """""" + # pylint: disable=old-style-class + def __init__(self): # currently assignable child stems self.stem = [] @@ -35,31 +44,36 @@ class Dandelion(): self.lock = RLock() def poissonTimeout(self, start=None, average=0): + """""" + # pylint: disable=no-self-use if start is None: start = time() if average == 0: average = FLUFF_TRIGGER_MEAN_DELAY - return start + expovariate(1.0/average) + FLUFF_TRIGGER_FIXED_DELAY + return start + expovariate(1.0 / average) + FLUFF_TRIGGER_FIXED_DELAY def addHash(self, hashId, source=None, stream=1): + """""" if not state.dandelion: return with self.lock: self.hashMap[hashId] = Stem( - self.getNodeStem(source), - stream, - self.poissonTimeout()) + self.getNodeStem(source), + stream, + self.poissonTimeout()) def setHashStream(self, hashId, stream=1): + """""" with self.lock: if hashId in self.hashMap: self.hashMap[hashId] = Stem( - self.hashMap[hashId].child, - stream, - self.poissonTimeout()) + self.hashMap[hashId].child, + stream, + self.poissonTimeout()) def removeHash(self, hashId, reason="no reason specified"): - logging.debug("%s entering fluff mode due to %s.", ''.join('%02x'%ord(i) for i in hashId), reason) + """""" + logging.debug("%s entering fluff mode due to %s.", ''.join('%02x' % ord(i) for i in hashId), reason) with self.lock: try: del self.hashMap[hashId] @@ -67,12 +81,15 @@ class Dandelion(): pass def hasHash(self, hashId): + """""" return hashId in self.hashMap def objectChildStem(self, hashId): + """""" return self.hashMap[hashId].child def maybeAddStem(self, connection): + """""" # fewer than MAX_STEMS outbound connections at last reshuffle? with self.lock: if len(self.stem) < MAX_STEMS: @@ -83,8 +100,8 @@ class Dandelion(): self.hashMap[k] = Stem(connection, v.stream, self.poissonTimeout()) invQueue.put((v.stream, k, v.child)) - def maybeRemoveStem(self, connection): + """""" # is the stem active? with self.lock: if connection in self.stem: @@ -96,6 +113,7 @@ class Dandelion(): self.hashMap[k] = Stem(None, v.stream, self.poissonTimeout()) def pickStem(self, parent=None): + """""" try: # pick a random from available stems stem = choice(range(len(self.stem))) @@ -112,6 +130,7 @@ class Dandelion(): return None def getNodeStem(self, node=None): + """""" with self.lock: try: return self.nodeMap[node] @@ -120,15 +139,18 @@ class Dandelion(): return self.nodeMap[node] def expire(self): + """""" with self.lock: deadline = time() # only expire those that have a child node, i.e. those without a child not will stick around - toDelete = [[v.stream, k, v.child] for k, v in self.hashMap.iteritems() if v.timeout < deadline and v.child] + toDelete = [[v.stream, k, v.child] + for k, v in self.hashMap.iteritems() if v.timeout < deadline and v.child] for row in toDelete: self.removeHash(row[1], 'expiration') invQueue.put((row[0], row[1], row[2])) def reRandomiseStems(self): + """""" with self.lock: try: # random two connections diff --git a/src/network/https.py b/src/network/https.py deleted file mode 100644 index 151efcb8..00000000 --- a/src/network/https.py +++ /dev/null @@ -1,54 +0,0 @@ -import asyncore - -from http import HTTPClient -import paths -from tls import TLSHandshake - -# self.sslSock = ssl.wrap_socket(self.sock, keyfile = os.path.join(paths.codePath(), 'sslkeys', 'key.pem'), certfile = os.path.join(paths.codePath(), 'sslkeys', 'cert.pem'), server_side = not self.initiatedConnection, ssl_version=ssl.PROTOCOL_TLSv1, do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA') - - -class HTTPSClient(HTTPClient, TLSHandshake): - def __init__(self, host, path): - if not hasattr(self, '_map'): - asyncore.dispatcher.__init__(self) - self.tlsDone = False -# TLSHandshake.__init__(self, address=(host, 443), certfile='/home/shurdeek/src/PyBitmessage/sslsrc/keys/cert.pem', keyfile='/home/shurdeek/src/PyBitmessage/src/sslkeys/key.pem', server_side=False, ciphers='AECDH-AES256-SHA') - HTTPClient.__init__(self, host, path, connect=False) - TLSHandshake.__init__(self, address=(host, 443), server_side=False) - - def handle_connect(self): - TLSHandshake.handle_connect(self) - - def handle_close(self): - if self.tlsDone: - HTTPClient.close(self) - else: - TLSHandshake.close(self) - - def readable(self): - if self.tlsDone: - return HTTPClient.readable(self) - else: - return TLSHandshake.readable(self) - - def handle_read(self): - if self.tlsDone: - HTTPClient.handle_read(self) - else: - TLSHandshake.handle_read(self) - - def writable(self): - if self.tlsDone: - return HTTPClient.writable(self) - else: - return TLSHandshake.writable(self) - - def handle_write(self): - if self.tlsDone: - HTTPClient.handle_write(self) - else: - TLSHandshake.handle_write(self) - -if __name__ == "__main__": - client = HTTPSClient('anarchy.economicsofbitcoin.com', '/') - asyncore.loop() diff --git a/src/network/socks4a.py b/src/network/socks4a.py index 978ede04..d0e425db 100644 --- a/src/network/socks4a.py +++ b/src/network/socks4a.py @@ -1,27 +1,38 @@ +""" +src/network/socks4a.py +====================== +""" +# pylint: disable=attribute-defined-outside-init + import socket import struct -from proxy import Proxy, ProxyError, GeneralProxyError +from proxy import GeneralProxyError, Proxy, ProxyError + class Socks4aError(ProxyError): + """""" errorCodes = ("Request granted", - "Request rejected or failed", - "Request rejected because SOCKS server cannot connect to identd on the client", - "Request rejected because the client program and identd report different user-ids", - "Unknown error") + "Request rejected or failed", + "Request rejected because SOCKS server cannot connect to identd on the client", + "Request rejected because the client program and identd report different user-ids", + "Unknown error") class Socks4a(Proxy): + """""" def __init__(self, address=None): Proxy.__init__(self, address) self.ipaddr = None self.destport = address[1] def state_init(self): + """""" self.set_state("auth_done", 0) return True def state_pre_connect(self): + """""" # Get the response if self.read_buf[0:1] != chr(0x00).encode(): # bad data @@ -47,14 +58,17 @@ class Socks4a(Proxy): return True def proxy_sock_name(self): - return socket.inet_ntoa(self.__proxysockname[0]) + """""" + return socket.inet_ntoa(self.__proxysockname[0]) class Socks4aConnection(Socks4a): + """""" def __init__(self, address): Socks4a.__init__(self, address=address) def state_auth_done(self): + """""" # Now we can request the actual connection rmtrslv = False self.append_write_buf(struct.pack('>BBH', 0x04, 0x01, self.destination[1])) @@ -65,7 +79,7 @@ class Socks4aConnection(Socks4a): self.append_write_buf(self.ipaddr) except socket.error: # Well it's not an IP number, so it's probably a DNS name. - if Proxy._remote_dns: + if Proxy._remote_dns: # pylint: disable=protected-access # Resolve remotely rmtrslv = True self.ipaddr = None @@ -83,6 +97,7 @@ class Socks4aConnection(Socks4a): return True def state_pre_connect(self): + """""" try: return Socks4a.state_pre_connect(self) except Socks4aError as e: @@ -91,12 +106,14 @@ class Socks4aConnection(Socks4a): class Socks4aResolver(Socks4a): + """""" def __init__(self, host): self.host = host self.port = 8444 Socks4a.__init__(self, address=(self.host, self.port)) def state_auth_done(self): + """""" # Now we can request the actual connection self.append_write_buf(struct.pack('>BBH', 0x04, 0xF0, self.destination[1])) self.append_write_buf(struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01)) @@ -108,4 +125,5 @@ class Socks4aResolver(Socks4a): return True def resolved(self): + """""" print "Resolved %s as %s" % (self.host, self.proxy_sock_name())