commit
98cdf287c4
2
setup.py
2
setup.py
|
@ -83,7 +83,7 @@ if __name__ == "__main__":
|
||||||
'qrcode': ['qrcode'],
|
'qrcode': ['qrcode'],
|
||||||
'pyopencl': ['pyopencl'],
|
'pyopencl': ['pyopencl'],
|
||||||
'notify2': ['notify2'],
|
'notify2': ['notify2'],
|
||||||
'sound:platform_system=="Windows"': ['winsound']
|
'sound;platform_system=="Windows"': ['winsound']
|
||||||
},
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"License :: OSI Approved :: MIT License"
|
"License :: OSI Approved :: MIT License"
|
||||||
|
|
|
@ -342,13 +342,21 @@ class Main:
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
def daemonize(self):
|
def daemonize(self):
|
||||||
|
grandfatherPid = os.getpid()
|
||||||
|
parentPid = None
|
||||||
try:
|
try:
|
||||||
if os.fork():
|
if os.fork():
|
||||||
|
# unlock
|
||||||
|
shared.thisapp.cleanup()
|
||||||
|
# wait until grandchild ready
|
||||||
|
while True:
|
||||||
|
sleep(1)
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# fork not implemented
|
# fork not implemented
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
parentPid = os.getpid()
|
||||||
shared.thisapp.lock() # relock
|
shared.thisapp.lock() # relock
|
||||||
os.umask(0)
|
os.umask(0)
|
||||||
try:
|
try:
|
||||||
|
@ -358,6 +366,11 @@ class Main:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
if os.fork():
|
if os.fork():
|
||||||
|
# unlock
|
||||||
|
shared.thisapp.cleanup()
|
||||||
|
# wait until child ready
|
||||||
|
while True:
|
||||||
|
sleep(1)
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# fork not implemented
|
# fork not implemented
|
||||||
|
@ -374,6 +387,10 @@ class Main:
|
||||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||||
|
if parentPid:
|
||||||
|
# signal ready
|
||||||
|
os.kill(parentPid, signal.SIGTERM)
|
||||||
|
os.kill(grandfatherPid, signal.SIGTERM)
|
||||||
|
|
||||||
def setSignalHandler(self):
|
def setSignalHandler(self):
|
||||||
signal.signal(signal.SIGINT, helper_generic.signal_handler)
|
signal.signal(signal.SIGINT, helper_generic.signal_handler)
|
||||||
|
|
|
@ -69,7 +69,7 @@ import queues
|
||||||
import shutdown
|
import shutdown
|
||||||
import state
|
import state
|
||||||
from statusbar import BMStatusBar
|
from statusbar import BMStatusBar
|
||||||
import throttle
|
from network.asyncore_pollchoose import set_rates
|
||||||
from version import softwareVersion
|
from version import softwareVersion
|
||||||
import sound
|
import sound
|
||||||
|
|
||||||
|
@ -2287,16 +2287,16 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
int(float(self.settingsDialogInstance.ui.lineEditMaxDownloadRate.text()))))
|
int(float(self.settingsDialogInstance.ui.lineEditMaxDownloadRate.text()))))
|
||||||
BMConfigParser().set('bitmessagesettings', 'maxuploadrate', str(
|
BMConfigParser().set('bitmessagesettings', 'maxuploadrate', str(
|
||||||
int(float(self.settingsDialogInstance.ui.lineEditMaxUploadRate.text()))))
|
int(float(self.settingsDialogInstance.ui.lineEditMaxUploadRate.text()))))
|
||||||
except:
|
except ValueError:
|
||||||
QMessageBox.about(self, _translate("MainWindow", "Number needed"), _translate(
|
QMessageBox.about(self, _translate("MainWindow", "Number needed"), _translate(
|
||||||
"MainWindow", "Your maximum download and upload rate must be numbers. Ignoring what you typed."))
|
"MainWindow", "Your maximum download and upload rate must be numbers. Ignoring what you typed."))
|
||||||
|
else:
|
||||||
|
set_rates(BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate"),
|
||||||
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate"))
|
||||||
|
|
||||||
BMConfigParser().set('bitmessagesettings', 'maxoutboundconnections', str(
|
BMConfigParser().set('bitmessagesettings', 'maxoutboundconnections', str(
|
||||||
int(float(self.settingsDialogInstance.ui.lineEditMaxOutboundConnections.text()))))
|
int(float(self.settingsDialogInstance.ui.lineEditMaxOutboundConnections.text()))))
|
||||||
|
|
||||||
throttle.SendThrottle().resetLimit()
|
|
||||||
throttle.ReceiveThrottle().resetLimit()
|
|
||||||
|
|
||||||
BMConfigParser().set('bitmessagesettings', 'namecoinrpctype',
|
BMConfigParser().set('bitmessagesettings', 'namecoinrpctype',
|
||||||
self.settingsDialogInstance.getNamecoinType())
|
self.settingsDialogInstance.getNamecoinType())
|
||||||
BMConfigParser().set('bitmessagesettings', 'namecoinrpchost', str(
|
BMConfigParser().set('bitmessagesettings', 'namecoinrpchost', str(
|
||||||
|
|
|
@ -51,7 +51,7 @@ def signal_handler(signal, frame):
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
if "PoolWorker" in current_process().name:
|
if "PoolWorker" in current_process().name:
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
if current_thread().name != "PyBitmessage":
|
if current_thread().name not in ("PyBitmessage", "MainThread"):
|
||||||
return
|
return
|
||||||
logger.error("Got signal %i", signal)
|
logger.error("Got signal %i", signal)
|
||||||
if BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon'):
|
if BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon'):
|
||||||
|
|
|
@ -75,7 +75,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
def writable(self):
|
def writable(self):
|
||||||
self.uploadChunk = AdvancedDispatcher._buf_len
|
self.uploadChunk = AdvancedDispatcher._buf_len
|
||||||
if asyncore.maxUploadRate > 0:
|
if asyncore.maxUploadRate > 0:
|
||||||
self.uploadChunk = 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))
|
||||||
|
@ -83,7 +83,7 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
def readable(self):
|
def readable(self):
|
||||||
self.downloadChunk = AdvancedDispatcher._buf_len
|
self.downloadChunk = AdvancedDispatcher._buf_len
|
||||||
if asyncore.maxDownloadRate > 0:
|
if asyncore.maxDownloadRate > 0:
|
||||||
self.downloadChunk = asyncore.downloadBucket
|
self.downloadChunk = int(asyncore.downloadBucket)
|
||||||
try:
|
try:
|
||||||
if self.expectBytes > 0 and not self.fullyEstablished:
|
if self.expectBytes > 0 and not self.fullyEstablished:
|
||||||
self.downloadChunk = min(self.downloadChunk, self.expectBytes - len(self.read_buf))
|
self.downloadChunk = min(self.downloadChunk, self.expectBytes - len(self.read_buf))
|
||||||
|
|
|
@ -112,6 +112,8 @@ uploadBucket = 0
|
||||||
sentBytes = 0
|
sentBytes = 0
|
||||||
|
|
||||||
def read(obj):
|
def read(obj):
|
||||||
|
if not can_receive():
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
obj.handle_read_event()
|
obj.handle_read_event()
|
||||||
except _reraised_exceptions:
|
except _reraised_exceptions:
|
||||||
|
@ -120,6 +122,8 @@ def read(obj):
|
||||||
obj.handle_error()
|
obj.handle_error()
|
||||||
|
|
||||||
def write(obj):
|
def write(obj):
|
||||||
|
if not can_send():
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
obj.handle_write_event()
|
obj.handle_write_event()
|
||||||
except _reraised_exceptions:
|
except _reraised_exceptions:
|
||||||
|
@ -129,19 +133,25 @@ def write(obj):
|
||||||
|
|
||||||
def set_rates(download, upload):
|
def set_rates(download, upload):
|
||||||
global maxDownloadRate, maxUploadRate, downloadBucket, uploadBucket, downloadTimestamp, uploadTimestamp
|
global maxDownloadRate, maxUploadRate, downloadBucket, uploadBucket, downloadTimestamp, uploadTimestamp
|
||||||
maxDownloadRate = float(download)
|
maxDownloadRate = float(download) * 1024
|
||||||
maxUploadRate = float(upload)
|
maxUploadRate = float(upload) * 1024
|
||||||
downloadBucket = maxDownloadRate
|
downloadBucket = maxDownloadRate
|
||||||
uploadBucket = maxUploadRate
|
uploadBucket = maxUploadRate
|
||||||
downloadTimestamp = time.time()
|
downloadTimestamp = time.time()
|
||||||
uploadTimestamp = time.time()
|
uploadTimestamp = time.time()
|
||||||
|
|
||||||
|
def can_receive():
|
||||||
|
return maxDownloadRate == 0 or downloadBucket > 0
|
||||||
|
|
||||||
|
def can_send():
|
||||||
|
return maxUploadRate == 0 or uploadBucket > 0
|
||||||
|
|
||||||
def update_received(download=0):
|
def update_received(download=0):
|
||||||
global receivedBytes, downloadBucket, downloadTimestamp
|
global receivedBytes, downloadBucket, downloadTimestamp
|
||||||
currentTimestamp = time.time()
|
currentTimestamp = time.time()
|
||||||
receivedBytes += download
|
receivedBytes += download
|
||||||
if maxDownloadRate > 0:
|
if maxDownloadRate > 0:
|
||||||
bucketIncrease = int(maxDownloadRate * (currentTimestamp - downloadTimestamp))
|
bucketIncrease = maxDownloadRate * (currentTimestamp - downloadTimestamp)
|
||||||
downloadBucket += bucketIncrease
|
downloadBucket += bucketIncrease
|
||||||
if downloadBucket > maxDownloadRate:
|
if downloadBucket > maxDownloadRate:
|
||||||
downloadBucket = int(maxDownloadRate)
|
downloadBucket = int(maxDownloadRate)
|
||||||
|
@ -153,7 +163,7 @@ def update_sent(upload=0):
|
||||||
currentTimestamp = time.time()
|
currentTimestamp = time.time()
|
||||||
sentBytes += upload
|
sentBytes += upload
|
||||||
if maxUploadRate > 0:
|
if maxUploadRate > 0:
|
||||||
bucketIncrease = int(maxUploadRate * (currentTimestamp - uploadTimestamp))
|
bucketIncrease = maxUploadRate * (currentTimestamp - uploadTimestamp)
|
||||||
uploadBucket += bucketIncrease
|
uploadBucket += bucketIncrease
|
||||||
if uploadBucket > maxUploadRate:
|
if uploadBucket > maxUploadRate:
|
||||||
uploadBucket = int(maxUploadRate)
|
uploadBucket = int(maxUploadRate)
|
||||||
|
@ -170,9 +180,9 @@ def _exception(obj):
|
||||||
|
|
||||||
def readwrite(obj, flags):
|
def readwrite(obj, flags):
|
||||||
try:
|
try:
|
||||||
if flags & select.POLLIN:
|
if flags & select.POLLIN and can_receive():
|
||||||
obj.handle_read_event()
|
obj.handle_read_event()
|
||||||
if flags & select.POLLOUT:
|
if flags & select.POLLOUT and can_send():
|
||||||
obj.handle_write_event()
|
obj.handle_write_event()
|
||||||
if flags & select.POLLPRI:
|
if flags & select.POLLPRI:
|
||||||
obj.handle_expt_event()
|
obj.handle_expt_event()
|
||||||
|
|
|
@ -8,23 +8,28 @@ from network.dandelion import Dandelion
|
||||||
import protocol
|
import protocol
|
||||||
import state
|
import state
|
||||||
|
|
||||||
class BMObjectInsufficientPOWError(Exception): pass
|
class BMObjectInsufficientPOWError(Exception):
|
||||||
|
errorCodes = ("Insufficient proof of work")
|
||||||
|
|
||||||
|
|
||||||
class BMObjectInvalidDataError(Exception): pass
|
class BMObjectInvalidDataError(Exception):
|
||||||
|
errorCodes = ("Data invalid")
|
||||||
|
|
||||||
|
|
||||||
class BMObjectExpiredError(Exception): pass
|
class BMObjectExpiredError(Exception):
|
||||||
|
errorCodes = ("Object expired")
|
||||||
|
|
||||||
|
|
||||||
class BMObjectUnwantedStreamError(Exception): pass
|
class BMObjectUnwantedStreamError(Exception):
|
||||||
|
errorCodes = ("Object in unwanted stream")
|
||||||
|
|
||||||
|
|
||||||
class BMObjectInvalidError(Exception): pass
|
class BMObjectInvalidError(Exception):
|
||||||
|
errorCodes = ("Invalid object")
|
||||||
|
|
||||||
|
|
||||||
class BMObjectAlreadyHaveError(Exception):
|
class BMObjectAlreadyHaveError(Exception):
|
||||||
pass
|
errorCodes = ("Already have this object")
|
||||||
|
|
||||||
|
|
||||||
class BMObject(object):
|
class BMObject(object):
|
||||||
|
|
|
@ -24,13 +24,16 @@ import shared
|
||||||
import state
|
import state
|
||||||
import protocol
|
import protocol
|
||||||
|
|
||||||
class BMProtoError(ProxyError): pass
|
class BMProtoError(ProxyError):
|
||||||
|
errorCodes = ("Protocol error")
|
||||||
|
|
||||||
|
|
||||||
class BMProtoInsufficientDataError(BMProtoError): pass
|
class BMProtoInsufficientDataError(BMProtoError):
|
||||||
|
errorCodes = ("Insufficient data")
|
||||||
|
|
||||||
|
|
||||||
class BMProtoExcessiveDataError(BMProtoError): pass
|
class BMProtoExcessiveDataError(BMProtoError):
|
||||||
|
errorCodes = ("Too much data")
|
||||||
|
|
||||||
|
|
||||||
class BMProto(AdvancedDispatcher, ObjectTracker):
|
class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
|
@ -494,6 +497,20 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
return False
|
return False
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
if not self.isOutbound:
|
||||||
|
# incoming from a peer we're connected to as outbound, or server full
|
||||||
|
# report the same error to counter deanonymisation
|
||||||
|
if state.Peer(self.destination.host, self.peerNode.port) in \
|
||||||
|
network.connectionpool.BMConnectionPool().inboundConnections or \
|
||||||
|
len(network.connectionpool.BMConnectionPool().inboundConnections) + \
|
||||||
|
len(network.connectionpool.BMConnectionPool().outboundConnections) > \
|
||||||
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxtotalconnections") + \
|
||||||
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxbootstrapconnections"):
|
||||||
|
self.append_write_buf(protocol.assembleErrorMessage(fatal=2,
|
||||||
|
errorText="Server full, please try again later."))
|
||||||
|
logger.debug ("Closed connection to %s due to server full or duplicate inbound/outbound.",
|
||||||
|
str(self.destination))
|
||||||
|
return False
|
||||||
if network.connectionpool.BMConnectionPool().isAlreadyConnected(self.nonce):
|
if network.connectionpool.BMConnectionPool().isAlreadyConnected(self.nonce):
|
||||||
self.append_write_buf(protocol.assembleErrorMessage(fatal=2,
|
self.append_write_buf(protocol.assembleErrorMessage(fatal=2,
|
||||||
errorText="I'm connected to myself. Closing connection."))
|
errorText="I'm connected to myself. Closing connection."))
|
||||||
|
|
|
@ -22,8 +22,8 @@ import state
|
||||||
class BMConnectionPool(object):
|
class BMConnectionPool(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
asyncore.set_rates(
|
asyncore.set_rates(
|
||||||
BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate") * 1024,
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate"),
|
||||||
BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate") * 1024)
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate"))
|
||||||
self.outboundConnections = {}
|
self.outboundConnections = {}
|
||||||
self.inboundConnections = {}
|
self.inboundConnections = {}
|
||||||
self.listeningSockets = {}
|
self.listeningSockets = {}
|
||||||
|
@ -65,12 +65,18 @@ class BMConnectionPool(object):
|
||||||
def getConnectionByAddr(self, addr):
|
def getConnectionByAddr(self, addr):
|
||||||
if addr in self.inboundConnections:
|
if addr in self.inboundConnections:
|
||||||
return self.inboundConnections[addr]
|
return self.inboundConnections[addr]
|
||||||
if addr.host in self.inboundConnections:
|
try:
|
||||||
return self.inboundConnections[addr.host]
|
if addr.host in self.inboundConnections:
|
||||||
|
return self.inboundConnections[addr.host]
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
if addr in self.outboundConnections:
|
if addr in self.outboundConnections:
|
||||||
return self.outboundConnections[addr]
|
return self.outboundConnections[addr]
|
||||||
if addr.host in self.udpSockets:
|
try:
|
||||||
return self.udpSockets[addr.host]
|
if addr.host in self.udpSockets:
|
||||||
|
return self.udpSockets[addr.host]
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
def isAlreadyConnected(self, nodeid):
|
def isAlreadyConnected(self, nodeid):
|
||||||
|
|
|
@ -43,7 +43,7 @@ class DownloadThread(threading.Thread, StoppableThread):
|
||||||
connections = BMConnectionPool().inboundConnections.values() + BMConnectionPool().outboundConnections.values()
|
connections = BMConnectionPool().inboundConnections.values() + BMConnectionPool().outboundConnections.values()
|
||||||
random.shuffle(connections)
|
random.shuffle(connections)
|
||||||
try:
|
try:
|
||||||
requestChunk = max(int(DownloadThread.maxRequestChunk / len(connections)), 1)
|
requestChunk = max(int(min(DownloadThread.maxRequestChunk, len(missingObjects)) / len(connections)), 1)
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
requestChunk = 1
|
requestChunk = 1
|
||||||
for i in connections:
|
for i in connections:
|
||||||
|
@ -63,15 +63,14 @@ class DownloadThread(threading.Thread, StoppableThread):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
random.shuffle(request)
|
random.shuffle(request)
|
||||||
|
if len(request) > requestChunk - downloadPending:
|
||||||
|
request = request[:max(1, requestChunk - downloadPending)]
|
||||||
if not request:
|
if not request:
|
||||||
continue
|
continue
|
||||||
if len(request) > requestChunk - downloadPending:
|
|
||||||
request = request[:requestChunk - downloadPending]
|
|
||||||
# mark them as pending
|
# mark them as pending
|
||||||
for k in request:
|
for k in request:
|
||||||
i.objectsNewToMe[k] = False
|
i.objectsNewToMe[k] = False
|
||||||
missingObjects[k] = now
|
missingObjects[k] = now
|
||||||
|
|
||||||
payload = bytearray()
|
payload = bytearray()
|
||||||
payload.extend(addresses.encodeVarint(len(request)))
|
payload.extend(addresses.encodeVarint(len(request)))
|
||||||
for chunk in request:
|
for chunk in request:
|
||||||
|
|
|
@ -29,6 +29,7 @@ class ObjectTracker(object):
|
||||||
invInitialCapacity = 50000
|
invInitialCapacity = 50000
|
||||||
invErrorRate = 0.03
|
invErrorRate = 0.03
|
||||||
trackingExpires = 3600
|
trackingExpires = 3600
|
||||||
|
initialTimeOffset = 60
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.objectsNewToMe = {}
|
self.objectsNewToMe = {}
|
||||||
|
@ -87,7 +88,7 @@ class ObjectTracker(object):
|
||||||
if hashId in Dandelion().hashMap:
|
if hashId in Dandelion().hashMap:
|
||||||
Dandelion().fluffTrigger(hashId)
|
Dandelion().fluffTrigger(hashId)
|
||||||
if hashId not in missingObjects:
|
if hashId not in missingObjects:
|
||||||
missingObjects[hashId] = time.time()
|
missingObjects[hashId] = time.time() - ObjectTracker.initialTimeOffset
|
||||||
with self.objectsNewToMeLock:
|
with self.objectsNewToMeLock:
|
||||||
self.objectsNewToMe[hashId] = True
|
self.objectsNewToMe[hashId] = True
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import state
|
||||||
class ProxyError(Exception):
|
class ProxyError(Exception):
|
||||||
errorCodes = ("UnknownError")
|
errorCodes = ("UnknownError")
|
||||||
|
|
||||||
def __init__(self, code):
|
def __init__(self, code=-1):
|
||||||
self.code = code
|
self.code = code
|
||||||
try:
|
try:
|
||||||
self.message = self.__class__.errorCodes[self.code]
|
self.message = self.__class__.errorCodes[self.code]
|
||||||
|
|
|
@ -180,7 +180,7 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
payload += hash
|
payload += hash
|
||||||
objectCount += 1
|
objectCount += 1
|
||||||
if objectCount >= BMProto.maxObjectCount:
|
if objectCount >= BMProto.maxObjectCount:
|
||||||
self.sendChunk()
|
sendChunk()
|
||||||
payload = b''
|
payload = b''
|
||||||
objectCount = 0
|
objectCount = 0
|
||||||
|
|
||||||
|
@ -292,7 +292,10 @@ class TCPServer(AdvancedDispatcher):
|
||||||
if len(network.connectionpool.BMConnectionPool().inboundConnections) + \
|
if len(network.connectionpool.BMConnectionPool().inboundConnections) + \
|
||||||
len(network.connectionpool.BMConnectionPool().outboundConnections) > \
|
len(network.connectionpool.BMConnectionPool().outboundConnections) > \
|
||||||
BMConfigParser().safeGetInt("bitmessagesettings", "maxtotalconnections") + \
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxtotalconnections") + \
|
||||||
BMConfigParser().safeGetInt("bitmessagesettings", "maxbootstrapconnections"):
|
BMConfigParser().safeGetInt("bitmessagesettings", "maxbootstrapconnections") + 10:
|
||||||
|
# 10 is a sort of buffer, in between it will go through the version handshake
|
||||||
|
# and return an error to the peer
|
||||||
|
logger.warning("Server full, dropping connection")
|
||||||
sock.close()
|
sock.close()
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -9,14 +9,12 @@ from helper_sql import sqlQuery, sqlStoredProcedure
|
||||||
from helper_threading import StoppableThread
|
from helper_threading import StoppableThread
|
||||||
from knownnodes import saveKnownNodes
|
from knownnodes import saveKnownNodes
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
import protocol
|
|
||||||
from queues import addressGeneratorQueue, objectProcessorQueue, UISignalQueue, workerQueue
|
from queues import addressGeneratorQueue, objectProcessorQueue, UISignalQueue, workerQueue
|
||||||
import shared
|
import shared
|
||||||
import state
|
import state
|
||||||
|
|
||||||
def doCleanShutdown():
|
def doCleanShutdown():
|
||||||
state.shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit.
|
state.shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit.
|
||||||
protocol.broadcastToSendDataQueues((0, 'shutdown', 'no data'))
|
|
||||||
objectProcessorQueue.put(('checkShutdownVariable', 'no data'))
|
objectProcessorQueue.put(('checkShutdownVariable', 'no data'))
|
||||||
for thread in threading.enumerate():
|
for thread in threading.enumerate():
|
||||||
if thread.isAlive() and isinstance(thread, StoppableThread):
|
if thread.isAlive() and isinstance(thread, StoppableThread):
|
||||||
|
|
|
@ -78,6 +78,15 @@ class singleinstance:
|
||||||
return
|
return
|
||||||
if self.daemon and self.lockPid == os.getpid():
|
if self.daemon and self.lockPid == os.getpid():
|
||||||
# these are the two initial forks while daemonizing
|
# these are the two initial forks while daemonizing
|
||||||
|
try:
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
if hasattr(self, 'fd'):
|
||||||
|
os.close(self.fd)
|
||||||
|
else:
|
||||||
|
fcntl.lockf(self.fp, fcntl.LOCK_UN)
|
||||||
|
except Exception, e:
|
||||||
|
pass
|
||||||
|
|
||||||
return
|
return
|
||||||
print "Cleaning up lockfile"
|
print "Cleaning up lockfile"
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
softwareName = 'PyBitmessage'
|
||||||
softwareVersion = '0.6.2'
|
softwareVersion = '0.6.2'
|
||||||
|
|
Reference in New Issue
Block a user