Node class, WIP
- for new network subsystem
This commit is contained in:
parent
23b9555929
commit
d9d3515905
|
@ -1,66 +1,66 @@
|
||||||
import socket
|
import time
|
||||||
import protocol
|
|
||||||
|
from inventory import PendingDownloadQueue
|
||||||
|
|
||||||
|
try:
|
||||||
|
# pybloomfiltermmap
|
||||||
|
from pybloomfilter import BloomFilter
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
# pybloom
|
||||||
|
from pybloom import BloomFilter
|
||||||
|
except ImportError:
|
||||||
|
# bundled pybloom
|
||||||
|
from fallback.pybloom import BloomFilter
|
||||||
|
|
||||||
|
|
||||||
class Node(object):
|
class Node(object):
|
||||||
TYPE_IPV4 = 1
|
invCleanPeriod = 300
|
||||||
TYPE_IPV6 = 2
|
invInitialCapacity = 50000
|
||||||
TYPE_ONION = 3
|
invErrorRate = 0.03
|
||||||
TYPE_LOCAL = 4
|
|
||||||
TYPE_LOOPBACK = 8
|
|
||||||
TYPE_UNDEF = 12
|
|
||||||
|
|
||||||
def __init__(self, services, address, port):
|
def __init__(self):
|
||||||
self.services = services
|
self.initInvBloom()
|
||||||
self.address, self.addressType = Node.decodeIPAddress(address)
|
self.initAddrBloom()
|
||||||
self.port = port
|
|
||||||
|
|
||||||
def isLocal(self):
|
def initInvBloom(self):
|
||||||
return self.addressType | Node.TYPE_LOCAL > 0
|
# lock?
|
||||||
|
self.invBloom = BloomFilter(capacity=Node.invInitialCapacity,
|
||||||
|
error_rate=Node.invErrorRate)
|
||||||
|
|
||||||
def isGlobal(self):
|
def initAddrBloom(self):
|
||||||
return self.addressType <= Node.TYPE_ONION
|
# lock?
|
||||||
|
self.addrBloom = BloomFilter(capacity=Node.invInitialCapacity,
|
||||||
|
error_rate=Node.invErrorRate)
|
||||||
|
|
||||||
def isOnion(self):
|
def cleanBloom(self):
|
||||||
return self.addressType | Node.TYPE_ONION > 0
|
if self.lastcleaned < time.time() - Node.invCleanPeriod:
|
||||||
|
if PendingDownloadQueue().size() == 0:
|
||||||
|
self.initInvBloom()
|
||||||
|
self.initAddrBloom()
|
||||||
|
|
||||||
def isLoopback(self):
|
def hasInv(self, hashid):
|
||||||
return self.addressType | Node.TYPE_LOOPBACK > 0
|
return hashid in self.invBloom
|
||||||
|
|
||||||
@staticmethod
|
def addInv(self, hashid):
|
||||||
def decodeIPAddress(host):
|
self.invBloom.add(hashid)
|
||||||
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
|
||||||
hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:])
|
|
||||||
return Node.decodeIPv4Address(host[12:], hostStandardFormat)
|
|
||||||
elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43':
|
|
||||||
# Onion, based on BMD/bitcoind
|
|
||||||
hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion"
|
|
||||||
return hostStandardFormat, Node.TYPE_ONION
|
|
||||||
else:
|
|
||||||
hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host)
|
|
||||||
if hostStandardFormat == "":
|
|
||||||
# This can happen on Windows systems which are not 64-bit compatible
|
|
||||||
# so let us drop the IPv6 address.
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV6|Node.TYPE_UNDEF
|
|
||||||
return Node.decodeIPv6Address(host, hostStandardFormat)
|
|
||||||
|
|
||||||
@staticmethod
|
def hasAddr(self, hashid):
|
||||||
def decodeIPv4Address(host, hostStandardFormat):
|
return hashid in self.invBloom
|
||||||
if host[0] == '\x7F': # 127/8
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOOPBACK
|
def addInv(self, hashid):
|
||||||
if host[0] == '\x0A': # 10/8
|
self.invBloom.add(hashid)
|
||||||
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
|
||||||
if host[0:2] == '\xC0\xA8': # 192.168/16
|
# addr sending -> per node upload queue, and flush every minute or so
|
||||||
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
# inv sending -> if not in bloom, inv immediately, otherwise put into a per node upload queue and flush every minute or so
|
||||||
if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
# no bloom
|
||||||
return hostStandardFormat, Node.TYPE_IPV4
|
# - if inv arrives
|
||||||
|
# - if we don't have it, add tracking and download queue
|
||||||
|
# - if we do have it, remove from tracking
|
||||||
|
# tracking downloads
|
||||||
|
# - per node hash of items the node has but we don't
|
||||||
|
# tracking inv
|
||||||
|
# - per node hash of items that neither the remote node nor we have
|
||||||
|
#
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _checkIPv6Address(host, hostStandardFormat):
|
|
||||||
if host == ('\x00' * 15) + '\x01':
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV6|Node.TYPE_LOOPBACK
|
|
||||||
if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80:
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV6|Node.TYPE_LOCAL
|
|
||||||
if (ord(host[0]) & 0xfe) == 0xfc:
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV6|Node.TYPE_UNDEF
|
|
||||||
return hostStandardFormat, Node.TYPE_IPV6
|
|
||||||
|
|
Reference in New Issue
Block a user