Skip to content

Commit 175916d

Browse files
authored
Merge pull request #1356 from coffeedogs/final_code_quality_3
Changes based on style and lint checks. (final_code_quality_3)
2 parents 2d4cb1e + c875769 commit 175916d

File tree

3 files changed

+102
-24
lines changed

3 files changed

+102
-24
lines changed

dev/ssltest.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,57 @@
88
HOST = "127.0.0.1"
99
PORT = 8912
1010

11+
1112
def sslProtocolVersion():
1213
# sslProtocolVersion
13-
if sys.version_info >= (2,7,13):
14+
if sys.version_info >= (2, 7, 13):
1415
# this means TLSv1 or higher
1516
# in the future change to
1617
# ssl.PROTOCOL_TLS1.2
1718
return ssl.PROTOCOL_TLS
18-
elif sys.version_info >= (2,7,9):
19+
elif sys.version_info >= (2, 7, 9):
1920
# this means any SSL/TLS. SSLv2 and 3 are excluded with an option after context is created
2021
return ssl.PROTOCOL_SSLv23
2122
else:
2223
# this means TLSv1, there is no way to set "TLSv1 or higher" or
2324
# "TLSv1.2" in < 2.7.9
2425
return ssl.PROTOCOL_TLSv1
2526

27+
2628
def sslProtocolCiphers():
2729
if ssl.OPENSSL_VERSION_NUMBER >= 0x10100000:
2830
return "AECDH-AES256-SHA@SECLEVEL=0"
2931
else:
3032
return "AECDH-AES256-SHA"
3133

34+
3235
def connect():
3336
sock = socket.create_connection((HOST, PORT))
3437
return sock
3538

39+
3640
def listen():
3741
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3842
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
3943
sock.bind((HOST, PORT))
4044
sock.listen(0)
4145
return sock
4246

47+
4348
def sslHandshake(sock, server=False):
44-
if sys.version_info >= (2,7,9):
49+
if sys.version_info >= (2, 7, 9):
4550
context = ssl.SSLContext(sslProtocolVersion())
4651
context.set_ciphers(sslProtocolCiphers())
4752
context.set_ecdh_curve("secp256k1")
4853
context.check_hostname = False
4954
context.verify_mode = ssl.CERT_NONE
5055
context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE | ssl.OP_CIPHER_SERVER_PREFERENCE
51-
sslSock = context.wrap_socket(sock, server_side = server, do_handshake_on_connect=False)
56+
sslSock = context.wrap_socket(sock, server_side=server, do_handshake_on_connect=False)
5257
else:
53-
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')
58+
sslSock = ssl.wrap_socket(sock, keyfile=os.path.join('src', 'sslkeys', 'key.pem'),
59+
certfile=os.path.join('src', 'sslkeys', 'cert.pem'),
60+
server_side=server, ssl_version=sslProtocolVersion(),
61+
do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA')
5462

5563
while True:
5664
try:
@@ -69,6 +77,7 @@ def sslHandshake(sock, server=False):
6977
print "Success!"
7078
return sslSock
7179

80+
7281
if __name__ == "__main__":
7382
if len(sys.argv) != 2:
7483
print "Usage: ssltest.py client|server"

src/network/advanceddispatcher.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
1+
"""
2+
src/network/advanceddispatcher.py
3+
=================================
4+
"""
5+
# pylint: disable=attribute-defined-outside-init
6+
17
import socket
28
import threading
39
import time
410

5-
import asyncore_pollchoose as asyncore
11+
import network.asyncore_pollchoose as asyncore
12+
import state
613
from debug import logger
714
from helper_threading import BusyError, nonBlocking
8-
import state
15+
916

1017
class ProcessingError(Exception):
18+
"""General class for protocol parser exception, use as a base for others."""
1119
pass
1220

21+
1322
class UnknownStateError(ProcessingError):
23+
"""Parser points to an unknown (unimplemented) state."""
1424
pass
1525

26+
1627
class AdvancedDispatcher(asyncore.dispatcher):
17-
_buf_len = 131072 # 128kB
28+
"""Improved version of asyncore dispatcher, with buffers and protocol state."""
29+
# pylint: disable=too-many-instance-attributes
30+
_buf_len = 131072 # 128kB
1831

1932
def __init__(self, sock=None):
2033
if not hasattr(self, '_map'):
@@ -31,6 +44,7 @@ def __init__(self, sock=None):
3144
self.processingLock = threading.RLock()
3245

3346
def append_write_buf(self, data):
47+
"""Append binary data to the end of stream write buffer."""
3448
if data:
3549
if isinstance(data, list):
3650
with self.writeLock:
@@ -41,6 +55,7 @@ def append_write_buf(self, data):
4155
self.write_buf.extend(data)
4256

4357
def slice_write_buf(self, length=0):
58+
"""Cut the beginning of the stream write buffer."""
4459
if length > 0:
4560
with self.writeLock:
4661
if length >= len(self.write_buf):
@@ -49,6 +64,7 @@ def slice_write_buf(self, length=0):
4964
del self.write_buf[0:length]
5065

5166
def slice_read_buf(self, length=0):
67+
"""Cut the beginning of the stream read buffer."""
5268
if length > 0:
5369
with self.readLock:
5470
if length >= len(self.read_buf):
@@ -57,6 +73,7 @@ def slice_read_buf(self, length=0):
5773
del self.read_buf[0:length]
5874

5975
def process(self):
76+
"""Process (parse) data that's in the buffer, as long as there is enough data and the connection is open."""
6077
while self.connected and not state.shutdown:
6178
try:
6279
with nonBlocking(self.processingLock):
@@ -68,27 +85,30 @@ def process(self):
6885
cmd = getattr(self, "state_" + str(self.state))
6986
except AttributeError:
7087
logger.error("Unknown state %s", self.state, exc_info=True)
71-
raise UnknownState(self.state)
88+
raise UnknownStateError(self.state)
7289
if not cmd():
7390
break
7491
except BusyError:
7592
return False
7693
return False
7794

78-
def set_state(self, state, length=0, expectBytes=0):
95+
def set_state(self, state_str, length=0, expectBytes=0):
96+
"""Set the next processing state."""
7997
self.expectBytes = expectBytes
8098
self.slice_read_buf(length)
81-
self.state = state
99+
self.state = state_str
82100

83101
def writable(self):
102+
"""Is data from the write buffer ready to be sent to the network?"""
84103
self.uploadChunk = AdvancedDispatcher._buf_len
85104
if asyncore.maxUploadRate > 0:
86105
self.uploadChunk = int(asyncore.uploadBucket)
87106
self.uploadChunk = min(self.uploadChunk, len(self.write_buf))
88107
return asyncore.dispatcher.writable(self) and \
89-
(self.connecting or (self.connected and self.uploadChunk > 0))
108+
(self.connecting or (self.connected and self.uploadChunk > 0))
90109

91110
def readable(self):
111+
"""Is the read buffer ready to accept data from the network?"""
92112
self.downloadChunk = AdvancedDispatcher._buf_len
93113
if asyncore.maxDownloadRate > 0:
94114
self.downloadChunk = int(asyncore.downloadBucket)
@@ -100,9 +120,10 @@ def readable(self):
100120
except AttributeError:
101121
pass
102122
return asyncore.dispatcher.readable(self) and \
103-
(self.connecting or self.accepting or (self.connected and self.downloadChunk > 0))
123+
(self.connecting or self.accepting or (self.connected and self.downloadChunk > 0))
104124

105125
def handle_read(self):
126+
"""Append incoming data to the read buffer."""
106127
self.lastTx = time.time()
107128
newData = self.recv(self.downloadChunk)
108129
self.receivedBytes += len(newData)
@@ -111,26 +132,32 @@ def handle_read(self):
111132
self.read_buf.extend(newData)
112133

113134
def handle_write(self):
135+
"""Send outgoing data from write buffer."""
114136
self.lastTx = time.time()
115137
written = self.send(self.write_buf[0:self.uploadChunk])
116138
asyncore.update_sent(written)
117139
self.sentBytes += written
118140
self.slice_write_buf(written)
119141

120142
def handle_connect_event(self):
143+
"""Callback for connection established event."""
121144
try:
122145
asyncore.dispatcher.handle_connect_event(self)
123146
except socket.error as e:
124-
if e.args[0] not in asyncore._DISCONNECTED:
147+
if e.args[0] not in asyncore._DISCONNECTED: # pylint: disable=protected-access
125148
raise
126149

127150
def handle_connect(self):
151+
"""Method for handling connection established implementations."""
128152
self.lastTx = time.time()
129153

130154
def state_close(self):
155+
"""Signal to the processing loop to end."""
156+
# pylint: disable=no-self-use
131157
return False
132158

133159
def handle_close(self):
160+
"""Callback for connection being closed, but can also be called directly when you want connection to close."""
134161
with self.readLock:
135162
self.read_buf = bytearray()
136163
with self.writeLock:

src/network/bmobject.py

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,68 @@
1-
from binascii import hexlify
1+
"""
2+
src/network/bmobject.py
3+
======================
4+
5+
"""
6+
27
import time
38

9+
import protocol
10+
import state
411
from addresses import calculateInventoryHash
512
from debug import logger
613
from inventory import Inventory
714
from network.dandelion import Dandelion
8-
import protocol
9-
import state
15+
1016

1117
class BMObjectInsufficientPOWError(Exception):
18+
"""Exception indicating the object doesn't have sufficient proof of work."""
1219
errorCodes = ("Insufficient proof of work")
1320

1421

1522
class BMObjectInvalidDataError(Exception):
23+
"""Exception indicating the data being parsed does not match the specification."""
1624
errorCodes = ("Data invalid")
1725

1826

1927
class BMObjectExpiredError(Exception):
28+
"""Exception indicating the object's lifetime has expired."""
2029
errorCodes = ("Object expired")
2130

2231

2332
class BMObjectUnwantedStreamError(Exception):
33+
"""Exception indicating the object is in a stream we didn't advertise as being interested in."""
2434
errorCodes = ("Object in unwanted stream")
2535

2636

2737
class BMObjectInvalidError(Exception):
38+
"""The object's data does not match object specification."""
2839
errorCodes = ("Invalid object")
2940

3041

3142
class BMObjectAlreadyHaveError(Exception):
43+
"""We received a duplicate object (one we already have)"""
3244
errorCodes = ("Already have this object")
3345

3446

3547
class BMObject(object):
48+
"""Bitmessage Object as a class."""
49+
# pylint: disable=too-many-instance-attributes
50+
3651
# max TTL, 28 days and 3 hours
3752
maxTTL = 28 * 24 * 60 * 60 + 10800
3853
# min TTL, 3 hour (in the past
3954
minTTL = -3600
4055

41-
def __init__(self, nonce, expiresTime, objectType, version, streamNumber, data, payloadOffset):
56+
def __init__(
57+
self,
58+
nonce,
59+
expiresTime,
60+
objectType,
61+
version,
62+
streamNumber,
63+
data,
64+
payloadOffset
65+
): # pylint: disable=too-many-arguments
4266
self.nonce = nonce
4367
self.expiresTime = expiresTime
4468
self.objectType = objectType
@@ -47,39 +71,50 @@ def __init__(self, nonce, expiresTime, objectType, version, streamNumber, data,
4771
self.inventoryHash = calculateInventoryHash(data)
4872
# copy to avoid memory issues
4973
self.data = bytearray(data)
50-
self.tag = self.data[payloadOffset:payloadOffset+32]
74+
self.tag = self.data[payloadOffset:payloadOffset + 32]
5175

5276
def checkProofOfWorkSufficient(self):
77+
"""Perform a proof of work check for sufficiency."""
5378
# Let us check to make sure that the proof of work is sufficient.
5479
if not protocol.isProofOfWorkSufficient(self.data):
5580
logger.info('Proof of work is insufficient.')
5681
raise BMObjectInsufficientPOWError()
5782

5883
def checkEOLSanity(self):
84+
"""Check if object's lifetime isn't ridiculously far in the past or future."""
5985
# EOL sanity check
6086
if self.expiresTime - int(time.time()) > BMObject.maxTTL:
61-
logger.info('This object\'s End of Life time is too far in the future. Ignoring it. Time is %i', self.expiresTime)
62-
# TODO: remove from download queue
87+
logger.info(
88+
'This object\'s End of Life time is too far in the future. Ignoring it. Time is %i',
89+
self.expiresTime)
90+
# .. todo:: remove from download queue
6391
raise BMObjectExpiredError()
6492

6593
if self.expiresTime - int(time.time()) < BMObject.minTTL:
66-
logger.info('This object\'s End of Life time was too long ago. Ignoring the object. Time is %i', self.expiresTime)
67-
# TODO: remove from download queue
94+
logger.info(
95+
'This object\'s End of Life time was too long ago. Ignoring the object. Time is %i',
96+
self.expiresTime)
97+
# .. todo:: remove from download queue
6898
raise BMObjectExpiredError()
6999

70100
def checkStream(self):
101+
"""Check if object's stream matches streams we are interested in"""
71102
if self.streamNumber not in state.streamsInWhichIAmParticipating:
72103
logger.debug('The streamNumber %i isn\'t one we are interested in.', self.streamNumber)
73104
raise BMObjectUnwantedStreamError()
74105

75106
def checkAlreadyHave(self):
107+
"""
108+
Check if we already have the object (so that we don't duplicate it in inventory or advertise it unnecessarily)
109+
"""
76110
# if it's a stem duplicate, pretend we don't have it
77111
if Dandelion().hasHash(self.inventoryHash):
78112
return
79113
if self.inventoryHash in Inventory():
80114
raise BMObjectAlreadyHaveError()
81115

82116
def checkObjectByType(self):
117+
"""Call a object type specific check (objects can have additional checks based on their types)"""
83118
if self.objectType == protocol.OBJECT_GETPUBKEY:
84119
self.checkGetpubkey()
85120
elif self.objectType == protocol.OBJECT_PUBKEY:
@@ -91,21 +126,28 @@ def checkObjectByType(self):
91126
# other objects don't require other types of tests
92127

93128
def checkMessage(self):
129+
""""Message" object type checks."""
130+
# pylint: disable=no-self-use
94131
return
95132

96133
def checkGetpubkey(self):
134+
""""Getpubkey" object type checks."""
97135
if len(self.data) < 42:
98136
logger.info('getpubkey message doesn\'t contain enough data. Ignoring.')
99137
raise BMObjectInvalidError()
100138

101139
def checkPubkey(self):
140+
""""Pubkey" object type checks."""
102141
if len(self.data) < 146 or len(self.data) > 440: # sanity check
103142
logger.info('pubkey object too short or too long. Ignoring.')
104143
raise BMObjectInvalidError()
105144

106145
def checkBroadcast(self):
146+
""""Broadcast" object type checks."""
107147
if len(self.data) < 180:
108-
logger.debug('The payload length of this broadcast packet is unreasonably low. Someone is probably trying funny business. Ignoring message.')
148+
logger.debug(
149+
'The payload length of this broadcast packet is unreasonably low.'
150+
' Someone is probably trying funny business. Ignoring message.')
109151
raise BMObjectInvalidError()
110152

111153
# this isn't supported anymore

0 commit comments

Comments
 (0)