67 lines
2.6 KiB
Python
67 lines
2.6 KiB
Python
import socket
|
|
import protocol
|
|
|
|
class Node (object):
|
|
TYPE_IPV4 = 1
|
|
TYPE_IPV6 = 2
|
|
TYPE_ONION = 3
|
|
TYPE_LOCAL = 4
|
|
TYPE_LOOPBACK = 8
|
|
TYPE_UNDEF = 12
|
|
|
|
def __init__(self, services, address, port):
|
|
self.services = services
|
|
self.address, self.addressType = Node.decodeIPAddress(address)
|
|
self.port = port
|
|
|
|
def isLocal(self):
|
|
return self.addressType | Node.TYPE_LOCAL > 0
|
|
|
|
def isGlobal(self):
|
|
return self.addressType <= Node.TYPE_ONION
|
|
|
|
def isOnion(self):
|
|
return self.addressType | Node.TYPE_ONION > 0
|
|
|
|
def isLoopback(self):
|
|
return self.addressType | Node.TYPE_LOOPBACK > 0
|
|
|
|
@staticmethod
|
|
def decodeIPAddress(host):
|
|
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 decodeIPv4Address(host, hostStandardFormat):
|
|
if host[0] == '\x7F': # 127/8
|
|
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOOPBACK
|
|
if host[0] == '\x0A': # 10/8
|
|
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
|
if host[0:2] == '\xC0\xA8': # 192.168/16
|
|
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
|
if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12
|
|
return hostStandardFormat, Node.TYPE_IPV4|Node.TYPE_LOCAL
|
|
return hostStandardFormat, Node.TYPE_IPV4
|
|
|
|
@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
|