Changes based on style and lint checks. (final_code_quality_19) #1401
|
@ -1,14 +1,19 @@
|
||||||
|
"""
|
||||||
|
src/network/dandelion.py
|
||||||
|
========================
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from random import choice, sample, expovariate
|
from random import choice, expovariate, sample
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from bmconfigparser import BMConfigParser
|
|
||||||
import network.connectionpool
|
import network.connectionpool
|
||||||
|
import state
|
||||||
from debug import logging
|
from debug import logging
|
||||||
from queues import invQueue
|
from queues import invQueue
|
||||||
from singleton import Singleton
|
from singleton import Singleton
|
||||||
import state
|
|
||||||
|
|
||||||
# randomise routes after 600 seconds
|
# randomise routes after 600 seconds
|
||||||
REASSIGN_INTERVAL = 600
|
REASSIGN_INTERVAL = 600
|
||||||
|
@ -21,8 +26,12 @@ MAX_STEMS = 2
|
||||||
|
|
||||||
Stem = namedtuple('Stem', ['child', 'stream', 'timeout'])
|
Stem = namedtuple('Stem', ['child', 'stream', 'timeout'])
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class Dandelion():
|
class Dandelion:
|
||||||
|
""""""
|
||||||
|
# pylint: disable=old-style-class
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# currently assignable child stems
|
# currently assignable child stems
|
||||||
self.stem = []
|
self.stem = []
|
||||||
|
@ -35,31 +44,36 @@ class Dandelion():
|
||||||
self.lock = RLock()
|
self.lock = RLock()
|
||||||
|
|
||||||
def poissonTimeout(self, start=None, average=0):
|
def poissonTimeout(self, start=None, average=0):
|
||||||
|
""""""
|
||||||
|
# pylint: disable=no-self-use
|
||||||
if start is None:
|
if start is None:
|
||||||
start = time()
|
start = time()
|
||||||
if average == 0:
|
if average == 0:
|
||||||
average = FLUFF_TRIGGER_MEAN_DELAY
|
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):
|
def addHash(self, hashId, source=None, stream=1):
|
||||||
|
""""""
|
||||||
PeterSurda
commented
Review
```suggestion
"""Dandelion class for tracking stem/fluff stages."""
```
|
|||||||
if not state.dandelion:
|
if not state.dandelion:
|
||||||
return
|
return
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.hashMap[hashId] = Stem(
|
self.hashMap[hashId] = Stem(
|
||||||
self.getNodeStem(source),
|
self.getNodeStem(source),
|
||||||
stream,
|
stream,
|
||||||
self.poissonTimeout())
|
self.poissonTimeout())
|
||||||
|
|
||||||
def setHashStream(self, hashId, stream=1):
|
def setHashStream(self, hashId, stream=1):
|
||||||
|
""""""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if hashId in self.hashMap:
|
if hashId in self.hashMap:
|
||||||
self.hashMap[hashId] = Stem(
|
self.hashMap[hashId] = Stem(
|
||||||
self.hashMap[hashId].child,
|
self.hashMap[hashId].child,
|
||||||
stream,
|
stream,
|
||||||
self.poissonTimeout())
|
self.poissonTimeout())
|
||||||
|
|
||||||
def removeHash(self, hashId, reason="no reason specified"):
|
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:
|
with self.lock:
|
||||||
try:
|
try:
|
||||||
del self.hashMap[hashId]
|
del self.hashMap[hashId]
|
||||||
|
@ -67,12 +81,15 @@ class Dandelion():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def hasHash(self, hashId):
|
def hasHash(self, hashId):
|
||||||
|
""""""
|
||||||
```suggestion
"""Generate deadline using Poisson distribution"""
```
|
|||||||
return hashId in self.hashMap
|
return hashId in self.hashMap
|
||||||
|
|
||||||
def objectChildStem(self, hashId):
|
def objectChildStem(self, hashId):
|
||||||
|
""""""
|
||||||
return self.hashMap[hashId].child
|
return self.hashMap[hashId].child
|
||||||
|
|
||||||
def maybeAddStem(self, connection):
|
def maybeAddStem(self, connection):
|
||||||
|
""""""
|
||||||
# fewer than MAX_STEMS outbound connections at last reshuffle?
|
# fewer than MAX_STEMS outbound connections at last reshuffle?
|
||||||
with self.lock:
|
with self.lock:
|
||||||
```suggestion
"""Add inventory vector to dandelion stem"""
```
|
|||||||
if len(self.stem) < MAX_STEMS:
|
if len(self.stem) < MAX_STEMS:
|
||||||
|
@ -83,8 +100,8 @@ class Dandelion():
|
||||||
self.hashMap[k] = Stem(connection, v.stream, self.poissonTimeout())
|
self.hashMap[k] = Stem(connection, v.stream, self.poissonTimeout())
|
||||||
invQueue.put((v.stream, k, v.child))
|
invQueue.put((v.stream, k, v.child))
|
||||||
|
|
||||||
|
|
||||||
def maybeRemoveStem(self, connection):
|
def maybeRemoveStem(self, connection):
|
||||||
|
""""""
|
||||||
# is the stem active?
|
# is the stem active?
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if connection in self.stem:
|
if connection in self.stem:
|
||||||
```suggestion
"""Update stream for inventory vector (as inv/dinv commands don't include streams, we only learn this after receiving the object)"""
```
|
|||||||
|
@ -96,6 +113,7 @@ class Dandelion():
|
||||||
self.hashMap[k] = Stem(None, v.stream, self.poissonTimeout())
|
self.hashMap[k] = Stem(None, v.stream, self.poissonTimeout())
|
||||||
|
|
||||||
def pickStem(self, parent=None):
|
def pickStem(self, parent=None):
|
||||||
|
""""""
|
||||||
try:
|
try:
|
||||||
# pick a random from available stems
|
# pick a random from available stems
|
||||||
stem = choice(range(len(self.stem)))
|
stem = choice(range(len(self.stem)))
|
||||||
|
@ -112,6 +130,7 @@ class Dandelion():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getNodeStem(self, node=None):
|
def getNodeStem(self, node=None):
|
||||||
|
""""""
|
||||||
```suggestion
"""Child (i.e. next) node for an inventory vector during stem mode"""
```
|
|||||||
with self.lock:
|
with self.lock:
|
||||||
try:
|
try:
|
||||||
return self.nodeMap[node]
|
return self.nodeMap[node]
|
||||||
|
@ -120,15 +139,18 @@ class Dandelion():
|
||||||
return self.nodeMap[node]
|
return self.nodeMap[node]
|
||||||
|
|
||||||
def expire(self):
|
def expire(self):
|
||||||
|
""""""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
deadline = time()
|
deadline = time()
|
||||||
# only expire those that have a child node, i.e. those without a child not will stick around
|
# 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:
|
for row in toDelete:
|
||||||
self.removeHash(row[1], 'expiration')
|
self.removeHash(row[1], 'expiration')
|
||||||
invQueue.put((row[0], row[1], row[2]))
|
invQueue.put((row[0], row[1], row[2]))
|
||||||
|
|
||||||
def reRandomiseStems(self):
|
def reRandomiseStems(self):
|
||||||
|
""""""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
try:
|
try:
|
||||||
# random two connections
|
# random two connections
|
||||||
|
|
|
@ -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()
|
|
|
@ -1,27 +1,38 @@
|
||||||
|
"""
|
||||||
|
src/network/socks4a.py
|
||||||
|
======================
|
||||||
|
"""
|
||||||
|
# pylint: disable=attribute-defined-outside-init
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from proxy import Proxy, ProxyError, GeneralProxyError
|
from proxy import GeneralProxyError, Proxy, ProxyError
|
||||||
|
|
||||||
|
|
||||||
class Socks4aError(ProxyError):
|
class Socks4aError(ProxyError):
|
||||||
|
""""""
|
||||||
errorCodes = ("Request granted",
|
errorCodes = ("Request granted",
|
||||||
```suggestion
"""SOCKS4a error base class"""
```
|
|||||||
"Request rejected or failed",
|
"Request rejected or failed",
|
||||||
"Request rejected because SOCKS server cannot connect to identd on the client",
|
"Request rejected because SOCKS server cannot connect to identd on the client",
|
||||||
"Request rejected because the client program and identd report different user-ids",
|
"Request rejected because the client program and identd report different user-ids",
|
||||||
"Unknown error")
|
"Unknown error")
|
||||||
|
|
||||||
|
|
||||||
class Socks4a(Proxy):
|
class Socks4a(Proxy):
|
||||||
|
""""""
|
||||||
def __init__(self, address=None):
|
def __init__(self, address=None):
|
||||||
Proxy.__init__(self, address)
|
Proxy.__init__(self, address)
|
||||||
self.ipaddr = None
|
self.ipaddr = None
|
||||||
self.destport = address[1]
|
self.destport = address[1]
|
||||||
|
|
||||||
```suggestion
"""SOCKS4a proxy class"""
```
|
|||||||
def state_init(self):
|
def state_init(self):
|
||||||
|
""""""
|
||||||
self.set_state("auth_done", 0)
|
self.set_state("auth_done", 0)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def state_pre_connect(self):
|
def state_pre_connect(self):
|
||||||
|
""""""
|
||||||
```suggestion
"""Protocol initialisation (before connection is established)"""
```
|
|||||||
# Get the response
|
# Get the response
|
||||||
if self.read_buf[0:1] != chr(0x00).encode():
|
if self.read_buf[0:1] != chr(0x00).encode():
|
||||||
# bad data
|
# bad data
|
||||||
|
@ -47,14 +58,17 @@ class Socks4a(Proxy):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def proxy_sock_name(self):
|
def proxy_sock_name(self):
|
||||||
return socket.inet_ntoa(self.__proxysockname[0])
|
""""""
|
||||||
|
return socket.inet_ntoa(self.__proxysockname[0])
|
||||||
|
|
||||||
|
|
||||||
class Socks4aConnection(Socks4a):
|
class Socks4aConnection(Socks4a):
|
||||||
|
""""""
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
Socks4a.__init__(self, address=address)
|
Socks4a.__init__(self, address=address)
|
||||||
|
|
||||||
def state_auth_done(self):
|
def state_auth_done(self):
|
||||||
|
""""""
|
||||||
# Now we can request the actual connection
|
# Now we can request the actual connection
|
||||||
rmtrslv = False
|
rmtrslv = False
|
||||||
self.append_write_buf(struct.pack('>BBH', 0x04, 0x01, self.destination[1]))
|
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)
|
self.append_write_buf(self.ipaddr)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
# Well it's not an IP number, so it's probably a DNS name.
|
# 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
|
# Resolve remotely
|
||||||
rmtrslv = True
|
rmtrslv = True
|
||||||
self.ipaddr = None
|
self.ipaddr = None
|
||||||
|
@ -83,6 +97,7 @@ class Socks4aConnection(Socks4a):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def state_pre_connect(self):
|
def state_pre_connect(self):
|
||||||
|
""""""
|
||||||
try:
|
try:
|
||||||
return Socks4a.state_pre_connect(self)
|
return Socks4a.state_pre_connect(self)
|
||||||
except Socks4aError as e:
|
except Socks4aError as e:
|
||||||
|
@ -91,12 +106,14 @@ class Socks4aConnection(Socks4a):
|
||||||
|
|
||||||
```suggestion
"""Handle return value when using SOCKS4a for DNS resolving instead of connecting."""
```
|
|||||||
|
|
||||||
class Socks4aResolver(Socks4a):
|
class Socks4aResolver(Socks4a):
|
||||||
|
""""""
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
self.host = host
|
self.host = host
|
||||||
```suggestion
"""Child SOCKS4a class used for making outbound connections."""
```
|
|||||||
self.port = 8444
|
self.port = 8444
|
||||||
Socks4a.__init__(self, address=(self.host, self.port))
|
Socks4a.__init__(self, address=(self.host, self.port))
|
||||||
|
|
||||||
def state_auth_done(self):
|
def state_auth_done(self):
|
||||||
|
""""""
|
||||||
```suggestion
"""Request connection to be made"""
```
|
|||||||
# Now we can request the actual connection
|
# 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('>BBH', 0x04, 0xF0, self.destination[1]))
|
||||||
self.append_write_buf(struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01))
|
self.append_write_buf(struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01))
|
||||||
|
@ -108,4 +125,5 @@ class Socks4aResolver(Socks4a):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def resolved(self):
|
def resolved(self):
|
||||||
|
""""""
|
||||||
print "Resolved %s as %s" % (self.host, self.proxy_sock_name())
|
print "Resolved %s as %s" % (self.host, self.proxy_sock_name())
|
||||||
|
|
Reference in New Issue
Block a user