Changes based on style and lint checks. (final_code_quality_3) #1356
|
@ -8,14 +8,15 @@ import traceback
|
||||||
HOST = "127.0.0.1"
|
HOST = "127.0.0.1"
|
||||||
PORT = 8912
|
PORT = 8912
|
||||||
|
|
||||||
|
|
||||||
def sslProtocolVersion():
|
def sslProtocolVersion():
|
||||||
# sslProtocolVersion
|
# sslProtocolVersion
|
||||||
if sys.version_info >= (2,7,13):
|
if sys.version_info >= (2, 7, 13):
|
||||||
# this means TLSv1 or higher
|
# this means TLSv1 or higher
|
||||||
# in the future change to
|
# in the future change to
|
||||||
# ssl.PROTOCOL_TLS1.2
|
# ssl.PROTOCOL_TLS1.2
|
||||||
return ssl.PROTOCOL_TLS
|
return ssl.PROTOCOL_TLS
|
||||||
elif sys.version_info >= (2,7,9):
|
elif sys.version_info >= (2, 7, 9):
|
||||||
# this means any SSL/TLS. SSLv2 and 3 are excluded with an option after context is created
|
# this means any SSL/TLS. SSLv2 and 3 are excluded with an option after context is created
|
||||||
return ssl.PROTOCOL_SSLv23
|
return ssl.PROTOCOL_SSLv23
|
||||||
else:
|
else:
|
||||||
|
@ -23,16 +24,19 @@ def sslProtocolVersion():
|
||||||
# "TLSv1.2" in < 2.7.9
|
# "TLSv1.2" in < 2.7.9
|
||||||
return ssl.PROTOCOL_TLSv1
|
return ssl.PROTOCOL_TLSv1
|
||||||
|
|
||||||
|
|
||||||
def sslProtocolCiphers():
|
def sslProtocolCiphers():
|
||||||
if ssl.OPENSSL_VERSION_NUMBER >= 0x10100000:
|
if ssl.OPENSSL_VERSION_NUMBER >= 0x10100000:
|
||||||
return "AECDH-AES256-SHA@SECLEVEL=0"
|
return "AECDH-AES256-SHA@SECLEVEL=0"
|
||||||
else:
|
else:
|
||||||
return "AECDH-AES256-SHA"
|
return "AECDH-AES256-SHA"
|
||||||
|
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
sock = socket.create_connection((HOST, PORT))
|
sock = socket.create_connection((HOST, PORT))
|
||||||
return sock
|
return sock
|
||||||
|
|
||||||
|
|
||||||
def listen():
|
def listen():
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
@ -40,17 +44,21 @@ def listen():
|
||||||
sock.listen(0)
|
sock.listen(0)
|
||||||
return sock
|
return sock
|
||||||
|
|
||||||
|
|
||||||
def sslHandshake(sock, server=False):
|
def sslHandshake(sock, server=False):
|
||||||
if sys.version_info >= (2,7,9):
|
if sys.version_info >= (2, 7, 9):
|
||||||
context = ssl.SSLContext(sslProtocolVersion())
|
context = ssl.SSLContext(sslProtocolVersion())
|
||||||
context.set_ciphers(sslProtocolCiphers())
|
context.set_ciphers(sslProtocolCiphers())
|
||||||
context.set_ecdh_curve("secp256k1")
|
context.set_ecdh_curve("secp256k1")
|
||||||
context.check_hostname = False
|
context.check_hostname = False
|
||||||
context.verify_mode = ssl.CERT_NONE
|
context.verify_mode = ssl.CERT_NONE
|
||||||
context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE | ssl.OP_CIPHER_SERVER_PREFERENCE
|
context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE | ssl.OP_CIPHER_SERVER_PREFERENCE
|
||||||
sslSock = context.wrap_socket(sock, server_side = server, do_handshake_on_connect=False)
|
sslSock = context.wrap_socket(sock, server_side=server, do_handshake_on_connect=False)
|
||||||
else:
|
else:
|
||||||
sslSock = ssl.wrap_socket(sock, keyfile = os.path.join('src', 'sslkeys', 'key.pem'), certfile = os.path.join('src', 'sslkeys', 'cert.pem'), server_side = server, ssl_version=sslProtocolVersion(), do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA')
|
sslSock = ssl.wrap_socket(sock, keyfile=os.path.join('src', 'sslkeys', 'key.pem'),
|
||||||
|
certfile=os.path.join('src', 'sslkeys', 'cert.pem'),
|
||||||
|
server_side=server, ssl_version=sslProtocolVersion(),
|
||||||
|
do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -69,6 +77,7 @@ def sslHandshake(sock, server=False):
|
||||||
print "Success!"
|
print "Success!"
|
||||||
return sslSock
|
return sslSock
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print "Usage: ssltest.py client|server"
|
print "Usage: ssltest.py client|server"
|
||||||
|
|
|
@ -1,20 +1,33 @@
|
||||||
|
"""
|
||||||
|
src/network/advanceddispatcher.py
|
||||||
|
=================================
|
||||||
|
"""
|
||||||
|
# pylint: disable=attribute-defined-outside-init
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import asyncore_pollchoose as asyncore
|
import network.asyncore_pollchoose as asyncore
|
||||||
|
import state
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from helper_threading import BusyError, nonBlocking
|
from helper_threading import BusyError, nonBlocking
|
||||||
import state
|
|
||||||
|
|
||||||
class ProcessingError(Exception):
|
class ProcessingError(Exception):
|
||||||
|
"""General class for protocol parser exception, use as a base for others."""
|
||||||
pass
|
pass
|
||||||
|
|||||||
|
|
||||||
|
|
||||||
class UnknownStateError(ProcessingError):
|
class UnknownStateError(ProcessingError):
|
||||||
|
"""Parser points to an unknown (unimplemented) state."""
|
||||||
pass
|
pass
|
||||||
Parser points to an unknown (unimplemented) state. Parser points to an unknown (unimplemented) state.
|
|||||||
|
|
||||||
|
|
||||||
class AdvancedDispatcher(asyncore.dispatcher):
|
class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
_buf_len = 131072 # 128kB
|
"""Improved version of asyncore dispatcher, with buffers and protocol state."""
|
||||||
|
# pylint: disable=too-many-instance-attributes
|
||||||
Improved version of asyncore dispatcher, with buffers and protocol state. Improved version of asyncore dispatcher, with buffers and protocol state.
|
|||||||
|
_buf_len = 131072 # 128kB
|
||||||
|
|
||||||
def __init__(self, sock=None):
|
def __init__(self, sock=None):
|
||||||
if not hasattr(self, '_map'):
|
if not hasattr(self, '_map'):
|
||||||
|
@ -31,6 +44,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
self.processingLock = threading.RLock()
|
self.processingLock = threading.RLock()
|
||||||
|
|
||||||
def append_write_buf(self, data):
|
def append_write_buf(self, data):
|
||||||
|
"""Append binary data to the end of stream write buffer."""
|
||||||
if data:
|
if data:
|
||||||
if isinstance(data, list):
|
if isinstance(data, list):
|
||||||
with self.writeLock:
|
with self.writeLock:
|
||||||
|
@ -41,6 +55,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
self.write_buf.extend(data)
|
self.write_buf.extend(data)
|
||||||
|
|
||||||
def slice_write_buf(self, length=0):
|
def slice_write_buf(self, length=0):
|
||||||
|
"""Cut the beginning of the stream write buffer."""
|
||||||
if length > 0:
|
if length > 0:
|
||||||
with self.writeLock:
|
with self.writeLock:
|
||||||
if length >= len(self.write_buf):
|
if length >= len(self.write_buf):
|
||||||
|
@ -49,6 +64,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
del self.write_buf[0:length]
|
del self.write_buf[0:length]
|
||||||
|
|
||||||
def slice_read_buf(self, length=0):
|
def slice_read_buf(self, length=0):
|
||||||
|
"""Cut the beginning of the stream read buffer."""
|
||||||
if length > 0:
|
if length > 0:
|
||||||
with self.readLock:
|
with self.readLock:
|
||||||
if length >= len(self.read_buf):
|
if length >= len(self.read_buf):
|
||||||
|
@ -57,6 +73,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
del self.read_buf[0:length]
|
del self.read_buf[0:length]
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
|
"""Process (parse) data that's in the buffer, as long as there is enough data and the connection is open."""
|
||||||
while self.connected and not state.shutdown:
|
while self.connected and not state.shutdown:
|
||||||
try:
|
try:
|
||||||
with nonBlocking(self.processingLock):
|
with nonBlocking(self.processingLock):
|
||||||
|
@ -68,27 +85,30 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
cmd = getattr(self, "state_" + str(self.state))
|
cmd = getattr(self, "state_" + str(self.state))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.error("Unknown state %s", self.state, exc_info=True)
|
logger.error("Unknown state %s", self.state, exc_info=True)
|
||||||
raise UnknownState(self.state)
|
raise UnknownStateError(self.state)
|
||||||
if not cmd():
|
if not cmd():
|
||||||
break
|
break
|
||||||
except BusyError:
|
except BusyError:
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_state(self, state, length=0, expectBytes=0):
|
def set_state(self, state_str, length=0, expectBytes=0):
|
||||||
|
"""Set the next processing state."""
|
||||||
self.expectBytes = expectBytes
|
self.expectBytes = expectBytes
|
||||||
self.slice_read_buf(length)
|
self.slice_read_buf(length)
|
||||||
self.state = state
|
self.state = state_str
|
||||||
|
|
||||||
def writable(self):
|
def writable(self):
|
||||||
|
"""Is data from the write buffer ready to be sent to the network?"""
|
||||||
Cut the beginning of the stream write buffer. Cut the beginning of the stream write buffer.
|
|||||||
self.uploadChunk = AdvancedDispatcher._buf_len
|
self.uploadChunk = AdvancedDispatcher._buf_len
|
||||||
if asyncore.maxUploadRate > 0:
|
if asyncore.maxUploadRate > 0:
|
||||||
self.uploadChunk = int(asyncore.uploadBucket)
|
self.uploadChunk = int(asyncore.uploadBucket)
|
||||||
self.uploadChunk = min(self.uploadChunk, len(self.write_buf))
|
self.uploadChunk = min(self.uploadChunk, len(self.write_buf))
|
||||||
return asyncore.dispatcher.writable(self) and \
|
return asyncore.dispatcher.writable(self) and \
|
||||||
(self.connecting or (self.connected and self.uploadChunk > 0))
|
(self.connecting or (self.connected and self.uploadChunk > 0))
|
||||||
|
|
||||||
def readable(self):
|
def readable(self):
|
||||||
|
"""Is the read buffer ready to accept data from the network?"""
|
||||||
self.downloadChunk = AdvancedDispatcher._buf_len
|
self.downloadChunk = AdvancedDispatcher._buf_len
|
||||||
if asyncore.maxDownloadRate > 0:
|
if asyncore.maxDownloadRate > 0:
|
||||||
self.downloadChunk = int(asyncore.downloadBucket)
|
self.downloadChunk = int(asyncore.downloadBucket)
|
||||||
|
@ -100,9 +120,10 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
return asyncore.dispatcher.readable(self) and \
|
return asyncore.dispatcher.readable(self) and \
|
||||||
(self.connecting or self.accepting or (self.connected and self.downloadChunk > 0))
|
(self.connecting or self.accepting or (self.connected and self.downloadChunk > 0))
|
||||||
|
|
||||||
def handle_read(self):
|
def handle_read(self):
|
||||||
|
"""Append incoming data to the read buffer."""
|
||||||
self.lastTx = time.time()
|
self.lastTx = time.time()
|
||||||
newData = self.recv(self.downloadChunk)
|
newData = self.recv(self.downloadChunk)
|
||||||
self.receivedBytes += len(newData)
|
self.receivedBytes += len(newData)
|
||||||
|
@ -111,6 +132,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
self.read_buf.extend(newData)
|
self.read_buf.extend(newData)
|
||||||
|
|
||||||
def handle_write(self):
|
def handle_write(self):
|
||||||
|
"""Send outgoing data from write buffer."""
|
||||||
self.lastTx = time.time()
|
self.lastTx = time.time()
|
||||||
Process (parse) data that's in the buffer, as long as there is enough data and the connection is open. Process (parse) data that's in the buffer, as long as there is enough data and the connection is open.
|
|||||||
written = self.send(self.write_buf[0:self.uploadChunk])
|
written = self.send(self.write_buf[0:self.uploadChunk])
|
||||||
asyncore.update_sent(written)
|
asyncore.update_sent(written)
|
||||||
|
@ -118,19 +140,24 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
self.slice_write_buf(written)
|
self.slice_write_buf(written)
|
||||||
|
|
||||||
def handle_connect_event(self):
|
def handle_connect_event(self):
|
||||||
|
"""Callback for connection established event."""
|
||||||
try:
|
try:
|
||||||
asyncore.dispatcher.handle_connect_event(self)
|
asyncore.dispatcher.handle_connect_event(self)
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.args[0] not in asyncore._DISCONNECTED:
|
if e.args[0] not in asyncore._DISCONNECTED: # pylint: disable=protected-access
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def handle_connect(self):
|
def handle_connect(self):
|
||||||
|
"""Method for handling connection established implementations."""
|
||||||
self.lastTx = time.time()
|
self.lastTx = time.time()
|
||||||
|
|
||||||
def state_close(self):
|
def state_close(self):
|
||||||
|
"""Signal to the processing loop to end."""
|
||||||
|
# pylint: disable=no-self-use
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_close(self):
|
def handle_close(self):
|
||||||
|
"""Callback for connection being closed, but can also be called directly when you want connection to close."""
|
||||||
with self.readLock:
|
with self.readLock:
|
||||||
self.read_buf = bytearray()
|
self.read_buf = bytearray()
|
||||||
with self.writeLock:
|
with self.writeLock:
|
||||||
|
|
|
@ -1,44 +1,68 @@
|
||||||
from binascii import hexlify
|
"""
|
||||||
|
src/network/bmobject.py
|
||||||
|
======================
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import protocol
|
||||||
|
import state
|
||||||
from addresses import calculateInventoryHash
|
from addresses import calculateInventoryHash
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
import protocol
|
|
||||||
import state
|
|
||||||
|
|
||||||
class BMObjectInsufficientPOWError(Exception):
|
class BMObjectInsufficientPOWError(Exception):
|
||||||
|
"""Exception indicating the object doesn't have sufficient proof of work."""
|
||||||
errorCodes = ("Insufficient proof of work")
|
errorCodes = ("Insufficient proof of work")
|
||||||
|
|
||||||
Exception indicating the object doesn't have sufficient proof of work. Exception indicating the object doesn't have sufficient proof of work.
|
|||||||
|
|
||||||
class BMObjectInvalidDataError(Exception):
|
class BMObjectInvalidDataError(Exception):
|
||||||
|
"""Exception indicating the data being parsed does not match the specification."""
|
||||||
errorCodes = ("Data invalid")
|
errorCodes = ("Data invalid")
|
||||||
|
|
||||||
Exception indicating the data being parsed does not match the specification. Exception indicating the data being parsed does not match the specification.
|
|||||||
|
|
||||||
class BMObjectExpiredError(Exception):
|
class BMObjectExpiredError(Exception):
|
||||||
|
"""Exception indicating the object's lifetime has expired."""
|
||||||
errorCodes = ("Object expired")
|
errorCodes = ("Object expired")
|
||||||
|
|
||||||
Exception indicating the object's lifetime has expired. Exception indicating the object's lifetime has expired.
|
|||||||
|
|
||||||
class BMObjectUnwantedStreamError(Exception):
|
class BMObjectUnwantedStreamError(Exception):
|
||||||
|
"""Exception indicating the object is in a stream we didn't advertise as being interested in."""
|
||||||
errorCodes = ("Object in unwanted stream")
|
errorCodes = ("Object in unwanted stream")
|
||||||
|
|
||||||
Exception indicating the object is in a stream we didn't advertise as being interested in. Exception indicating the object is in a stream we didn't advertise as being interested in.
|
|||||||
|
|
||||||
class BMObjectInvalidError(Exception):
|
class BMObjectInvalidError(Exception):
|
||||||
|
"""The object's data does not match object specification."""
|
||||||
errorCodes = ("Invalid object")
|
errorCodes = ("Invalid object")
|
||||||
|
|
||||||
The object's data does not match object specification. The object's data does not match object specification.
|
|||||||
|
|
||||||
class BMObjectAlreadyHaveError(Exception):
|
class BMObjectAlreadyHaveError(Exception):
|
||||||
|
"""We received a duplicate object (one we already have)"""
|
||||||
errorCodes = ("Already have this object")
|
errorCodes = ("Already have this object")
|
||||||
|
|
||||||
We received a duplicate object (one we already have) We received a duplicate object (one we already have)
|
|||||||
|
|
||||||
class BMObject(object):
|
class BMObject(object):
|
||||||
|
"""Bitmessage Object as a class."""
|
||||||
|
# pylint: disable=too-many-instance-attributes
|
||||||
|
|
||||||
Bitmessage Object as a class. Bitmessage Object as a class.
|
|||||||
# max TTL, 28 days and 3 hours
|
# max TTL, 28 days and 3 hours
|
||||||
maxTTL = 28 * 24 * 60 * 60 + 10800
|
maxTTL = 28 * 24 * 60 * 60 + 10800
|
||||||
# min TTL, 3 hour (in the past
|
# min TTL, 3 hour (in the past
|
||||||
minTTL = -3600
|
minTTL = -3600
|
||||||
|
|
||||||
def __init__(self, nonce, expiresTime, objectType, version, streamNumber, data, payloadOffset):
|
def __init__(
|
||||||
|
self,
|
||||||
|
nonce,
|
||||||
|
expiresTime,
|
||||||
|
objectType,
|
||||||
|
version,
|
||||||
|
streamNumber,
|
||||||
|
data,
|
||||||
|
payloadOffset
|
||||||
|
): # pylint: disable=too-many-arguments
|
||||||
self.nonce = nonce
|
self.nonce = nonce
|
||||||
self.expiresTime = expiresTime
|
self.expiresTime = expiresTime
|
||||||
self.objectType = objectType
|
self.objectType = objectType
|
||||||
|
@ -47,32 +71,42 @@ class BMObject(object):
|
||||||
self.inventoryHash = calculateInventoryHash(data)
|
self.inventoryHash = calculateInventoryHash(data)
|
||||||
# copy to avoid memory issues
|
# copy to avoid memory issues
|
||||||
self.data = bytearray(data)
|
self.data = bytearray(data)
|
||||||
self.tag = self.data[payloadOffset:payloadOffset+32]
|
self.tag = self.data[payloadOffset:payloadOffset + 32]
|
||||||
|
|
||||||
def checkProofOfWorkSufficient(self):
|
def checkProofOfWorkSufficient(self):
|
||||||
|
"""Perform a proof of work check for sufficiency."""
|
||||||
# Let us check to make sure that the proof of work is sufficient.
|
# Let us check to make sure that the proof of work is sufficient.
|
||||||
if not protocol.isProofOfWorkSufficient(self.data):
|
if not protocol.isProofOfWorkSufficient(self.data):
|
||||||
logger.info('Proof of work is insufficient.')
|
logger.info('Proof of work is insufficient.')
|
||||||
raise BMObjectInsufficientPOWError()
|
raise BMObjectInsufficientPOWError()
|
||||||
|
|
||||||
def checkEOLSanity(self):
|
def checkEOLSanity(self):
|
||||||
|
"""Check if object's lifetime isn't ridiculously far in the past or future."""
|
||||||
# EOL sanity check
|
# EOL sanity check
|
||||||
if self.expiresTime - int(time.time()) > BMObject.maxTTL:
|
if self.expiresTime - int(time.time()) > BMObject.maxTTL:
|
||||||
logger.info('This object\'s End of Life time is too far in the future. Ignoring it. Time is %i', self.expiresTime)
|
logger.info(
|
||||||
# TODO: remove from download queue
|
'This object\'s End of Life time is too far in the future. Ignoring it. Time is %i',
|
||||||
|
self.expiresTime)
|
||||||
|
# .. todo:: remove from download queue
|
||||||
raise BMObjectExpiredError()
|
raise BMObjectExpiredError()
|
||||||
|
|
||||||
if self.expiresTime - int(time.time()) < BMObject.minTTL:
|
if self.expiresTime - int(time.time()) < BMObject.minTTL:
|
||||||
logger.info('This object\'s End of Life time was too long ago. Ignoring the object. Time is %i', self.expiresTime)
|
logger.info(
|
||||||
# TODO: remove from download queue
|
'This object\'s End of Life time was too long ago. Ignoring the object. Time is %i',
|
||||||
|
self.expiresTime)
|
||||||
|
# .. todo:: remove from download queue
|
||||||
raise BMObjectExpiredError()
|
raise BMObjectExpiredError()
|
||||||
|
|
||||||
def checkStream(self):
|
def checkStream(self):
|
||||||
|
"""Check if object's stream matches streams we are interested in"""
|
||||||
if self.streamNumber not in state.streamsInWhichIAmParticipating:
|
if self.streamNumber not in state.streamsInWhichIAmParticipating:
|
||||||
logger.debug('The streamNumber %i isn\'t one we are interested in.', self.streamNumber)
|
logger.debug('The streamNumber %i isn\'t one we are interested in.', self.streamNumber)
|
||||||
raise BMObjectUnwantedStreamError()
|
raise BMObjectUnwantedStreamError()
|
||||||
|
|
||||||
def checkAlreadyHave(self):
|
def checkAlreadyHave(self):
|
||||||
|
"""
|
||||||
|
Check if we already have the object (so that we don't duplicate it in inventory or advertise it unnecessarily)
|
||||||
|
"""
|
||||||
# if it's a stem duplicate, pretend we don't have it
|
# if it's a stem duplicate, pretend we don't have it
|
||||||
if Dandelion().hasHash(self.inventoryHash):
|
if Dandelion().hasHash(self.inventoryHash):
|
||||||
return
|
return
|
||||||
|
@ -80,6 +114,7 @@ class BMObject(object):
|
||||||
raise BMObjectAlreadyHaveError()
|
raise BMObjectAlreadyHaveError()
|
||||||
|
|
||||||
def checkObjectByType(self):
|
def checkObjectByType(self):
|
||||||
|
"""Call a object type specific check (objects can have additional checks based on their types)"""
|
||||||
if self.objectType == protocol.OBJECT_GETPUBKEY:
|
if self.objectType == protocol.OBJECT_GETPUBKEY:
|
||||||
self.checkGetpubkey()
|
self.checkGetpubkey()
|
||||||
elif self.objectType == protocol.OBJECT_PUBKEY:
|
elif self.objectType == protocol.OBJECT_PUBKEY:
|
||||||
|
@ -91,21 +126,28 @@ class BMObject(object):
|
||||||
# other objects don't require other types of tests
|
# other objects don't require other types of tests
|
||||||
|
|
||||||
def checkMessage(self):
|
def checkMessage(self):
|
||||||
|
""""Message" object type checks."""
|
||||||
|
# pylint: disable=no-self-use
|
||||||
return
|
return
|
||||||
|
|
||||||
def checkGetpubkey(self):
|
def checkGetpubkey(self):
|
||||||
|
""""Getpubkey" object type checks."""
|
||||||
if len(self.data) < 42:
|
if len(self.data) < 42:
|
||||||
logger.info('getpubkey message doesn\'t contain enough data. Ignoring.')
|
logger.info('getpubkey message doesn\'t contain enough data. Ignoring.')
|
||||||
raise BMObjectInvalidError()
|
raise BMObjectInvalidError()
|
||||||
|
|
||||||
def checkPubkey(self):
|
def checkPubkey(self):
|
||||||
|
""""Pubkey" object type checks."""
|
||||||
if len(self.data) < 146 or len(self.data) > 440: # sanity check
|
if len(self.data) < 146 or len(self.data) > 440: # sanity check
|
||||||
logger.info('pubkey object too short or too long. Ignoring.')
|
logger.info('pubkey object too short or too long. Ignoring.')
|
||||||
raise BMObjectInvalidError()
|
raise BMObjectInvalidError()
|
||||||
|
|
||||||
def checkBroadcast(self):
|
def checkBroadcast(self):
|
||||||
|
""""Broadcast" object type checks."""
|
||||||
if len(self.data) < 180:
|
if len(self.data) < 180:
|
||||||
logger.debug('The payload length of this broadcast packet is unreasonably low. Someone is probably trying funny business. Ignoring message.')
|
logger.debug(
|
||||||
|
'The payload length of this broadcast packet is unreasonably low.'
|
||||||
|
' Someone is probably trying funny business. Ignoring message.')
|
||||||
Perform a proof of work check for sufficiency. Perform a proof of work check for sufficiency.
|
|||||||
raise BMObjectInvalidError()
|
raise BMObjectInvalidError()
|
||||||
|
|
||||||
# this isn't supported anymore
|
# this isn't supported anymore
|
||||||
|
|
Reference in New Issue
Block a user
General class for protocol parser exception, use as a base for others.