03263156de
If this option is specified in keys.dat then Bitmessage will connect to the host specified there instead of connecting to the hosts in the list of known nodes. It will also stop listening for incoming connections and the timing attack mitigation will be disabled. The expected use case is for example where a user is running a daemon on a dedicated machine in their local network and they occasionally want to check for messages using a second instance of the client on their laptop. In that case it would be much faster to catch up with the messages by directly downloading from the dedicated machine over the LAN. There is no need to connect to multiple peers or to do the timing attack mitigation because the daemon is trusted. The host is specified as hostname:port. Eg, ‘192.168.1.8:8444’.
94 lines
4.2 KiB
Python
94 lines
4.2 KiB
Python
import threading
|
|
import shared
|
|
import socket
|
|
from class_sendDataThread import *
|
|
from class_receiveDataThread import *
|
|
import helper_bootstrap
|
|
|
|
# Only one singleListener thread will ever exist. It creates the
|
|
# receiveDataThread and sendDataThread for each incoming connection. Note
|
|
# that it cannot set the stream number because it is not known yet- the
|
|
# other node will have to tell us its stream number in a version message.
|
|
# If we don't care about their stream, we will close the connection
|
|
# (within the recversion function of the recieveData thread)
|
|
|
|
|
|
class singleListener(threading.Thread):
|
|
|
|
def __init__(self):
|
|
threading.Thread.__init__(self)
|
|
|
|
def setup(self, selfInitiatedConnections):
|
|
self.selfInitiatedConnections = selfInitiatedConnections
|
|
|
|
def run(self):
|
|
# If there is a trusted peer then we don't want to accept
|
|
# incoming connections so we'll just abandon the thread
|
|
if shared.trustedPeer:
|
|
return
|
|
|
|
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
|
|
time.sleep(1)
|
|
helper_bootstrap.dns()
|
|
# We typically don't want to accept incoming connections if the user is using a
|
|
# SOCKS proxy, unless they have configured otherwise. If they eventually select
|
|
# proxy 'none' or configure SOCKS listening then this will start listening for
|
|
# connections.
|
|
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and not shared.config.getboolean('bitmessagesettings', 'sockslisten'):
|
|
time.sleep(5)
|
|
|
|
with shared.printLock:
|
|
print 'Listening for incoming connections.'
|
|
|
|
HOST = '' # Symbolic name meaning all available interfaces
|
|
PORT = shared.config.getint('bitmessagesettings', 'port')
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
# This option apparently avoids the TIME_WAIT state so that we can
|
|
# rebind faster
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
sock.bind((HOST, PORT))
|
|
sock.listen(2)
|
|
|
|
while True:
|
|
# We typically don't want to accept incoming connections if the user is using a
|
|
# SOCKS proxy, unless they have configured otherwise. If they eventually select
|
|
# proxy 'none' or configure SOCKS listening then this will start listening for
|
|
# connections.
|
|
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and not shared.config.getboolean('bitmessagesettings', 'sockslisten'):
|
|
time.sleep(10)
|
|
while len(shared.connectedHostsList) > 220:
|
|
with shared.printLock:
|
|
print 'We are connected to too many people. Not accepting further incoming connections for ten seconds.'
|
|
|
|
time.sleep(10)
|
|
a, (HOST, PORT) = sock.accept()
|
|
|
|
# The following code will, unfortunately, block an incoming
|
|
# connection if someone else on the same LAN is already connected
|
|
# because the two computers will share the same external IP. This
|
|
# is here to prevent connection flooding.
|
|
while HOST in shared.connectedHostsList:
|
|
with shared.printLock:
|
|
print 'We are already connected to', HOST + '. Ignoring connection.'
|
|
|
|
a.close()
|
|
a, (HOST, PORT) = sock.accept()
|
|
someObjectsOfWhichThisRemoteNodeIsAlreadyAware = {} # This is not necessairly a complete list; we clear it from time to time to save memory.
|
|
sendDataThreadQueue = Queue.Queue() # Used to submit information to the send data thread for this connection.
|
|
a.settimeout(20)
|
|
|
|
sd = sendDataThread(sendDataThreadQueue)
|
|
sd.setup(
|
|
a, HOST, PORT, -1, someObjectsOfWhichThisRemoteNodeIsAlreadyAware)
|
|
sd.start()
|
|
|
|
rd = receiveDataThread()
|
|
rd.daemon = True # close the main program even if there are threads left
|
|
rd.setup(
|
|
a, HOST, PORT, -1, someObjectsOfWhichThisRemoteNodeIsAlreadyAware, self.selfInitiatedConnections, sendDataThreadQueue)
|
|
rd.start()
|
|
|
|
with shared.printLock:
|
|
print self, 'connected to', HOST, 'during INCOMING request.'
|
|
|